結果

問題 No.399 動的な領主
ユーザー yuki681yuki681
提出日時 2016-07-16 00:40:13
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 298 ms / 2,000 ms
コード長 2,915 bytes
コンパイル時間 2,191 ms
コンパイル使用メモリ 173,080 KB
実行使用メモリ 171,384 KB
最終ジャッジ日時 2024-04-25 08:49:32
合計ジャッジ時間 7,251 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 113 ms
150,528 KB
testcase_01 AC 114 ms
150,528 KB
testcase_02 AC 113 ms
150,656 KB
testcase_03 AC 112 ms
150,528 KB
testcase_04 AC 113 ms
150,656 KB
testcase_05 AC 123 ms
151,788 KB
testcase_06 AC 291 ms
163,296 KB
testcase_07 AC 298 ms
163,148 KB
testcase_08 AC 286 ms
162,732 KB
testcase_09 AC 290 ms
163,104 KB
testcase_10 AC 114 ms
150,784 KB
testcase_11 AC 122 ms
151,584 KB
testcase_12 AC 254 ms
162,004 KB
testcase_13 AC 253 ms
161,952 KB
testcase_14 AC 192 ms
171,300 KB
testcase_15 AC 212 ms
171,384 KB
testcase_16 AC 211 ms
165,912 KB
testcase_17 AC 291 ms
162,956 KB
testcase_18 AC 292 ms
162,712 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>
#define PB push_back
#define MP make_pair
#define int long long int

using namespace std;
typedef pair<int, int> PII;
typedef pair<PII, int> PPI;
typedef pair<int, PII> PIP;
typedef pair<PII, PII> PPP;
typedef vector<PII> VP;
typedef VP::iterator VPI;
typedef vector<int> VI;
const int INF = 3e18;
const double PI = acos(-1);

int n, q;
VI node[100001];
VI under[100001];
int a[100001], b[100001];
VP segarray;
int segnum[100001];
int pluss[100001], minuss[100001];
int ans = 0;

void input()
{
  scanf("%lld", &n);
  for(int i = 1; i <= n - 1; i++){
    int u, v;
    scanf("%lld%lld", &u, &v);
    node[u].PB(v);
    node[v].PB(u);
  }

  scanf("%lld", &q);
  for(int i = 0; i < q; i++){
    scanf("%lld%lld", &a[i], &b[i]);
  }
}

void dfs(int parent, int x, int deep)
{
  segnum[x] = segarray.size();
  segarray.PB(MP(deep, x));
  for(int i = 0; i < node[x].size(); i++){
    if(node[x][i] != parent){
      under[x].PB(node[x][i]);
      dfs(x, node[x][i], deep + 1);
      segarray.PB(MP(deep, x));
    }
  }
}

struct segtree
{
  PII tree[9000000];
  int size;

  void reset()
  {
    size = 1;
    while(size < segarray.size()){
      size <<= 1;
    }

    set(0, size - 1, 0);
  }
  PII set(int left, int right, int now)
  {
    if(left == right){
      if(left >= segarray.size()){
	return tree[now] = MP(INF, INF);
      }
      else{
	return tree[now] = segarray[left];
      }	
    }
    else{
      return tree[now] = min(set(left, (left + right) / 2, now * 2 + 1), set((left + right) / 2 + 1, right, now * 2 + 2));
    }
  }

  PII smallest(int start, int end, int left, int right, int now)
  {
    if(right < start || end < left){
      return MP(INF, INF);
    }
    if(start <= left && right <= end){
      return tree[now];
    }
    return min(smallest(start, end, left, (left + right) / 2, now * 2 + 1), smallest(start, end, (left + right) / 2 + 1, right, now * 2 + 2));
  }
} lcm;

void compedge(int x)
{
  int lcma = segnum[a[x]], lcmb = segnum[b[x]];
  if(lcma > lcmb) swap(lcma, lcmb);
  PII lcmed = lcm.smallest(lcma, lcmb, 0, lcm.size - 1, 0);
  if(lcmed.second == a[x]){
    pluss[b[x]]++;
    minuss[a[x]]--;
  }
  else if(lcmed.second == b[x]){
    pluss[a[x]]++;
    minuss[b[x]]--;
  }
  else{
    pluss[a[x]]++;
    pluss[b[x]]++;
    pluss[lcmed.second]--;
    minuss[lcmed.second]--;
  }
}

int sumdp[200000];
int calcsum(int now)
{
  if(now == 0)
    return 0;
  if(sumdp[now] != -1)
    return sumdp[now];
  return sumdp[now] = now + calcsum(now - 1);
}

int solve(int now)
{
  int sum = 0;
  for(int i = 0; i < under[now].size(); i++){
    sum += solve(under[now][i]);
  }
  sum += pluss[now];
  ans += calcsum(sum);
  sum += minuss[now];
  return sum;
}

signed main()
{
  input();
  dfs(0, 1, 0);
  lcm.reset();
  for(int i = 0; i < q; i++){
    compedge(i);
  }
  memset(sumdp, -1, sizeof sumdp);
  solve(1);
  printf("%lld\n", ans);

  return 0;
}
0