【BZOJ 1103】[POI2007]大都市meg
【链接】 我是链接,点我呀:)
【题意】
【题解】
dfs序 进入的位置设为1出去的设为-1则某个点进去的位置的dfs序的前缀和就是这个点到根节点的路径数。 (可以巧妙的把那些分叉路径去掉。 修改成公路后。就把下面的那个点(深度高的)的进入和出去的值都设置为0 用线段树维护区间和。 (可以用树状数组.【代码】
#include <bits/stdc++.h>
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const double pi = acos(-1);
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};
const int N = 25e4;
const int NN = 50e4;
int n,cnt,c[NN+10],_in[N+10],_out[N+10],sum[NN*4],_dep[N+10];
vector<int> g[N+10];
void dfs(int x,int fa,int dep){
cnt++;
c[cnt] = 1;
_in[x] = cnt;
_dep[x] = dep;
for (int i = 0;i < (int) g[x].size();i++){
int y = g[x][i];
if (y==fa) continue;
dfs(y,x,dep+1);
}
cnt++;
c[cnt] = -1;
_out[x] = cnt;
}
void build(int l,int r,int rt){
if (l==r){
sum[rt] = c[l];
return;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void updata(int pos,int l,int r,int rt){
if (l==r){
sum[rt] = 0;
c[pos] = 0;
return;
}
int mid = (l+r)>>1;
if (pos<= mid)
updata(pos,lson);
else
updata(pos,rson);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
int getsum(int L,int R,int l,int r,int rt){
if (L<=l && r <= R){
return sum[rt];
}
int mid = (l+r)>>1;
int temp1 = 0,temp2 = 0;
if (L<=mid) temp1 = getsum(L,R,lson);
if (mid < R) temp2 = getsum(L,R,rson);
return temp1 + temp2;
}
char s[5];
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
scanf("%d",&n);
for (int i = 1;i <= n-1;i++){
int a,b;
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,0,1);
build(1,cnt,1);
int m;
scanf("%d",&m);
for (int i = 1;i <= n + m - 1;i++){
scanf("%s",s);
if (s[0]=='W'){
int a;
scanf("%d",&a);
printf("%d\n",getsum(1,_in[a],1,cnt,1)-1);
}else{
int a,b;
scanf("%d%d",&a,&b);
if (_dep[a]<_dep[b]) swap(a,b);
updata(_in[a],1,cnt,1);
updata(_out[a],1,cnt,1);
}
}
return 0;
}