Tree CodeForces -932D

错误记录:如下注释语句

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5 LL log2n=19,cnt=1;
 6 LL anc[400010][20],maxv[400010][20],v[400010];
 7 LL anc2[400010][20],sum[400010][20];
 8 LL pow2[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288};
 9 //maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i
10 //sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i
11 LL Q,last;
12 int main()
13 {
14     LL i,idx,p,q,t,ans;
15     v[0]=1e15+1;
16     for(i=0;i<=log2n;i++)    maxv[1][i]=maxv[0][i]=sum[1][i]=sum[0][i]=1e15+1;
17     scanf("%lld",&Q);
18     while(Q--)
19     {
20         scanf("%lld%lld%lld",&idx,&p,&q);
21         p^=last;q^=last;
22         //printf("%lld %lld\n",p,q);
23         if(idx==1)
24         {
25             v[++cnt]=q;anc[cnt][0]=p;maxv[cnt][0]=v[anc[cnt][0]];
26             //putchar('a');printf("%d %d ",0,maxv[cnt][0]);
27             for(i=1;i<=log2n;i++)
28             {
29                 anc[cnt][i]=anc[anc[cnt][i-1]][i-1];
30                 maxv[cnt][i]=max(maxv[cnt][i-1],maxv[anc[cnt][i-1]][i-1]);
31                 //printf("%d %d ",i,maxv[cnt][i]);
32             }
33             //putchar('b');
34             for(t=cnt,i=log2n;i>=0;i--)
35                 if(maxv[t][i]<v[cnt])
36                     t=anc[t][i];
37             anc2[cnt][0]=anc[t][0];sum[cnt][0]=v[anc2[cnt][0]];
38             //printf("%d %d\n",cnt,nxt[cnt]);
39             //printf("%lld %lld ",0LL,sum[cnt][0]);
40             for(i=1;i<=log2n;i++)
41             {
42                 anc2[cnt][i]=anc2[anc2[cnt][i-1]][i-1];
43                 sum[cnt][i]=sum[cnt][i-1]+sum[anc2[cnt][i-1]][i-1];
44                 //printf("%lld %lld ",i,sum[cnt][i]);
45             }
46             //putchar('c');
47         }
48         else
49         {
50             q-=v[p];ans=1;if(q<0){ans=0;goto xxx;}
51             for(t=p,i=log2n;i>=0;i--)
52                 if(sum[t][i]<=q)
53                 {
54                     //t=anc2[t][i];
55                     q-=sum[t][i];ans+=pow2[i];//ans++
56                     t=anc2[t][i];
57                 }
58             xxx:last=ans;
59             printf("%lld\n",ans);
60         }
61     }
62     return 0;
63 }
View Code
另外,不能看到要加点就想动态树(不会)什么的,比如这道题,虽然要加点,但是仅此而已,用不到那些东西,只需要加入点时倍增求出要维护的值就行了。

对于原树,每加入一个节点u求出maxv(含义见程序),然后由这个新节点u向上倍增找到其祖先节点v,使得u到v的路径上所有点(不含u,含v)权值的最大值小于u的权值,且v深度最小。那么v的父节点就是u向上一级一级跳时第一个能访问到的权值大于等于u的节点,记为nxt[u](程序中省略,直接记为anc2[u][0])。

这样子,对于每个节点u(除了1号)都能得到nxt[u],把nxt[u]当做u的父节点,形成一棵新的树,那么查询转化为给定一个节点u,在新树上找到u的祖先节点v,使得u到v的路径上所有点(含u和v)权值之和小于等于x,且v的深度最小,输出u到v的路径上点数(含u和v)。(当然也可能u的权值就超过x了,那么输出0,要特判)。仍然倍增解决即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5 LL log2n=19,cnt=1;
 6 LL anc[400010][20],maxv[400010][20],v[400010];
 7 LL anc2[400010][20],sum[400010][20];
 8 //maxv[i][j]指i到其2^j级祖先的路径上点权最大值,含2^j级祖先,不含i
 9 //sum[i][j]指i到其2^j级祖先的路径上点权之和,含祖先,不含i
10 LL Q,last;
11 int main()
12 {
13     LL i,idx,p,q,t,ans;
14     v[0]=1e15+1;
15     for(i=0;i<=log2n;i++)    maxv[1][i]=maxv[0][i]=sum[1][i]=sum[0][i]=1e15+1;
16     scanf("%lld",&Q);
17     while(Q--)
18     {
19         scanf("%lld%lld%lld",&idx,&p,&q);
20         p^=last;q^=last;
21         if(idx==1)
22         {
23             v[++cnt]=q;anc[cnt][0]=p;maxv[cnt][0]=v[anc[cnt][0]];
24             for(i=1;i<=log2n;i++)
25             {
26                 anc[cnt][i]=anc[anc[cnt][i-1]][i-1];
27                 maxv[cnt][i]=max(maxv[cnt][i-1],maxv[anc[cnt][i-1]][i-1]);
28             }
29             for(t=cnt,i=log2n;i>=0;i--)
30                 if(maxv[t][i]<v[cnt])
31                     t=anc[t][i];
32             anc2[cnt][0]=anc[t][0];sum[cnt][0]=v[anc2[cnt][0]];
33             for(i=1;i<=log2n;i++)
34             {
35                 anc2[cnt][i]=anc2[anc2[cnt][i-1]][i-1];
36                 sum[cnt][i]=sum[cnt][i-1]+sum[anc2[cnt][i-1]][i-1];
37             }
38         }
39         else
40         {
41             q-=v[p];ans=1;if(q<0){ans=0;goto xxx;}
42             for(t=p,i=log2n;i>=0;i--)
43                 if(sum[t][i]<=q)
44                 {
45                     q-=sum[t][i];ans+=(1LL<<i);
46                     t=anc2[t][i];
47                 }
48             xxx:last=ans;
49             printf("%lld\n",ans);
50         }
51     }
52     return 0;
53 }

 

posted @ 2018-02-24 16:40  hehe_54321  阅读(260)  评论(0编辑  收藏  举报
AmazingCounters.com