poj 3321(dfs序&&树状数组)

来源:互联网 发布:ubuntu 16.10安装lamp 编辑:程序博客网 时间:2024/05/17 10:05

第一次知道dfs序这个东西,可以维护树上的任意一个节点,以这个节点为根的子树上的所有节点的标号。是连续的一段区间。

一棵子树的所有节点在dfs序里是连续一段,主要就是利用这个性质来解题

然后就是树状数组维护区间内苹果的数量

另外这个题很卡时间,我用了输入输出挂才过

#include<cstdio>#include<vector>using namespace std;const int maxn = 100000+10;vector<int>G[maxn];int l[maxn],r[maxn];int tree[maxn];char op[5];int x,key,n;inline int in(){    char ch;    int a = 0;    while((ch = getchar()) == ' ' || ch == '\n');    a += ch - '0';    while((ch = getchar()) != ' ' && ch != '\n')    {        a *= 10;        a += ch - '0';    }    return a;}void dfs(int u){    l[u] = key;    int len = G[u].size();    for(int i=0;i<len;i++)    {        int v = G[u][i];        key++;        dfs(v);    }    r[u] = key;}inline int lowbit(int i){return i&(-i);}inline void add(int i,int x){    while(i<=n)    {        tree[i] += x;        i += lowbit(i);    }}inline int getsum(int i){    int sum = 0;    while(i)    {        sum += tree[i];        i -= lowbit(i);    }    return sum;}int q[maxn];inline void Out(int a){   //  输出外挂    if (a < 0)    {        putchar('-');        a = -a;    }    if (a >= 10)    {       Out(a / 10);    }    putchar(a % 10 + '0');}int main(){    int u,v;    n = in();    for(int i=1;i<n;i++)    {        u = in(); v = in();        G[u].push_back(v);    }    key = 1;    dfs(1);    for(int i=1;i<=n;i++) q[i] = 1,add(i,1);    int m;    scanf("%d",&m);    while(m--)    {        scanf("%s%d",op,&x);        if(op[0]=='Q')        {            Out(getsum(r[x])-getsum(l[x]-1)); puts("");        }        else        {            if(q[x]==1) add(l[x],-1),q[x]=0;            else add(l[x],1),q[x] = 1;        }    }    return 0;}


原创粉丝点击