bzoj4196 [Noi2015]软件包管理器

  没啥可说的,树链剖分

  代码

  1 #include<cstdio>
  2 #define N 1000010
  3 int dp,pre[N],p[N],tt[N],size[N],f[N],gf[N];
  4 int l[N],r[N],go[N],v[N],s[N],tot,m;
  5 int L[N],R[N],n,a,i;
  6 char str[10];
  7 void link(int x,int y)
  8 {
  9     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
 10 }
 11 void dfs1(int x,int fa)
 12 {
 13     int i=p[x];
 14     size[x]=1;
 15     while (i)
 16     {
 17         dfs1(tt[i],x);
 18         size[x]+=size[tt[i]];
 19         f[tt[i]]=x;
 20         if (size[tt[i]]>size[go[x]]) go[x]=tt[i];
 21         i=pre[i];
 22     }
 23 }
 24 void dfs2(int x,int fa)
 25 {
 26     int i=p[x];
 27     L[x]=++tot;
 28     gf[x]=fa;
 29     if (go[x]) dfs2(go[x],fa);
 30     while (i)
 31     {
 32         if (tt[i]!=go[x]) dfs2(tt[i],tt[i]);
 33         i=pre[i];
 34     }
 35     R[x]=tot;
 36 }
 37 void build(int x,int a,int b)
 38 {
 39     l[x]=a;r[x]=b;
 40     if (b-a>1)
 41     {
 42         int m=(l[x]+r[x])>>1;
 43         build(2*x,a,m);
 44         build(2*x+1,m,b);
 45     }
 46 } 
 47 void clean(int x)
 48 {
 49     if (v[x]!=-1)
 50     {
 51         s[x]=(r[x]-l[x])*v[x];
 52         v[2*x]=v[x];
 53         v[2*x+1]=v[x];
 54         v[x]=-1;
 55     }
 56 }
 57 void change(int x,int a,int b,int c)
 58 {
 59     clean(x);
 60     if ((a<=l[x])&&(r[x]<=b))
 61     {
 62         v[x]=c;
 63         return;
 64     }
 65     int m=(l[x]+r[x])>>1;
 66     if (a<m) change(2*x,a,b,c);
 67     if (m<b) change(2*x+1,a,b,c);
 68     clean(2*x);clean(2*x+1);
 69     s[x]=s[2*x]+s[2*x+1];
 70 }
 71 int query(int x,int a,int b)
 72 {
 73     clean(x);
 74     if ((a<=l[x])&&(r[x]<=b))
 75         return s[x];
 76     int m=(l[x]+r[x])>>1,ans=0;
 77     if (a<m) ans+=query(2*x,a,b);
 78     if (m<b) ans+=query(2*x+1,a,b);
 79     return ans;
 80 }
 81 int getans(int x)
 82 {
 83     int ans=0;
 84     while (x)
 85     {
 86     //    printf("%d %d\n",L[gf[x]],L[x]);
 87         ans=ans+(L[x]-L[gf[x]]+1)-query(1,L[gf[x]]-1,L[x]);
 88         change(1,L[gf[x]]-1,L[x],1);
 89         x=f[gf[x]];
 90     }
 91     return ans;
 92 }
 93 int main()
 94 {
 95     scanf("%d",&n);
 96     for (i=2;i<=n;i++)
 97     {
 98         scanf("%d",&a);a++;
 99         link(a,i);
100     }
101     dfs1(1,0);
102     dfs2(1,1);
103     build(1,0,tot);
104     scanf("%d",&m);
105     for (i=1;i<=m;i++)
106     {
107         scanf("%s %d",str,&a);a++;
108         if (str[0]=='i')
109             printf("%d\n",getans(a));
110         else
111         {
112         //    printf("%d %d\n",L[a],R[a]);
113             printf("%d\n",query(1,L[a]-1,R[a]));
114             change(1,L[a]-1,R[a],0);
115         }
116     }
117 } 

 

转载于:https://www.cnblogs.com/fzmh/p/5410968.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值