题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1103

这题题目好长啊。。。第一眼我感觉树剖就好了,一看数据范围。。。然后想就想不出来了。。。感觉这题做法好妙啊!

首先求dfs序,比如样例就是1455422331,然后对于每个点,在它进入的时间+1,退出时-1,样例是:+1 +1 +1 -1 -1 +1 -1 +1 -1 -1

这样1~x的前缀和就是1到x的路径和了(想想为什么)

最后我们只要用一个树状数组来维护就好了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#include<vector>
#define mp make_pair
#define fi first
#define se second
#define sqr(x) (x)*(x)
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define per(i,x,y) for (int i=(x);i>=(y);i--)
using namespace std;
typedef long long LL;
typedef double DBD;
typedef pair<int,int> pa;
const int inf=1e9;
const LL INF=1e18;
//----------------------------head-----------------------------------//
const int N=250010,M=N<<1;
struct edge{int to,nxt;}e[M];
int n,m,head[N],cnt,c[M],in[N],out[N],ind,ljj;
char s[10];
int Write[20];
int read() {int d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;}
void write(int x){int t=0; if (x<0) putchar('-'),x=-x; for (;x;x/=10) Write[++t]=x%10; if (!t) putchar('0'); for (int i=t;i>=1;i--) putchar((char)(Write[i]+48));}
void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);}
void addedge(int x,int y)
{
    e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
    e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
}
void dfs(int u,int fa)
{
    in[u]=++ind;
    for (int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].to;
        if (v==fa) continue;
        dfs(v,u);
    }
    out[u]=++ind;
}
void update(int x,int v){for (int i=x;i<=ljj;i+=i&-i) c[i]+=v;}
int query(int x){int res=0; for (int i=x;i>=1;i-=i&-i) res+=c[i]; return res;}
int main()
{
    //judge();
    n=read(); ljj=n*2;
    for (int i=1;i<n;i++) addedge(read(),read());
    dfs(1,0);
    for (int i=1;i<=n;i++) update(in[i],1),update(out[i],-1);
    m=read(); m=n+m-1;
    while (m--)
    {
        scanf("%s",s);
        if (s[0]=='W')
        {
            int x=read();
            printf("%d\n",query(in[x])-1);
        }
        else
        {
            int x=read(),y=read();
            update(in[y],-1); update(out[y],1);
        }
    }
    return 0;
}
/*
5
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3
*/
View Code