卧薪尝胆,厚积薄发。
POI2007 大都市meg
Date: Wed Sep 12 08:09:42 CST 2018 In Category: NoCategory

Description:

给一棵树,每次可以将一条边从土路变成公路,或者询问从根节点到某个点的土路个数。
$1\le n \le 250000$

Solution:

先把这棵树的 $DFS$ 序求出来,进栈时 $+1$ 出栈时 $-1$ ,把边的权值下放到深度大的点,那么每个点进栈的位置求前缀和就是它到根节点的路径的土路个数,可以用树状数组维护。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
using namespace std;
inline char getc()
{
register char c = getchar();
while(c != 'W' && c != 'A')c = getchar();
return c;
}
int n,m;
#define MAXN 250010
struct edge
{
int to,nxt;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b,int id)
{
++edgenum;e[edgenum].to = b;e[edgenum].nxt = lin[a];lin[a] = edgenum;
++edgenum;e[edgenum].to = a;e[edgenum].nxt = lin[b];lin[b] = edgenum;
return;
}
bool v[MAXN];
int val[MAXN];
int dep[MAXN];
int ind[MAXN],outd[MAXN],tot = 0;
int lowbit(int x){return x & (-x);}
int f[MAXN << 1];
void add(int p,int x){for(int i = p;i <= 2 * n;i += lowbit(i))f[i] += x;return;}
int query(int p){int res = 0;for(int i = p;i >= 1;i -= lowbit(i))res += f[i];return res;}
void dfs(int k)
{
ind[k] = ++tot;if(k != 1)add(tot,1);
v[k] = true;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(!v[e[i].to])
{
dep[e[i].to] = dep[k] + 1;
dfs(e[i].to);
}
}
outd[k] = ++tot;if(k != 1)add(tot,-1);
return;
}
int main()
{
scanf("%d",&n);
int a,b;
for(int i = 1;i < n;++i)
{
scanf("%d%d",&a,&b);
add(a,b,i);
}
dfs(1);
scanf("%d",&m);
for(int i = 1;i <= n + m - 1;++i)
{
if(getc() == 'A')
{
scanf("%d%d",&a,&b);
if(dep[a] > dep[b])
{
add(ind[a],-1);
add(outd[a],1);
}
else
{
add(ind[b],-1);
add(outd[b],1);
}
}
else
{
scanf("%d",&a);
printf("%d\n",query(ind[a]));
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡