码迷,mamicode.com
首页 > 其他好文 > 详细

ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) ---d

时间:2018-02-21 11:44:23      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:namespace   eve   codeforce   get   splay   div   i++   closed   --   

D. Tree

 

最暴力的想法自然是,对于每一次询问,沿着父亲一点一点往上跳模拟。这样似乎并不能优化...

稍微好一点的想法是对于每一个点开一个nxt数组表示父亲中权值大于他的里面离他最近的在哪里,同样对于每一次询问模拟往上跳,每次加点模拟往上找,复杂度依旧没有变化,但为我们提供了一个思路,我们可以倍增啊!

首先我们对于2操作,我们记录sum[x][i]表示他的2^i个nxt的值的和是多少,这样我们就可以快速求出在总权值小于x的前提下最多能跳到哪里。

考虑如何求出这个数组。

定义nxt[x][i]为x的第2^i个nxt是谁。

对于每一次加点操作,我们记录fa[x][i]表示x的第2^i个父亲是谁,同时记录这些父亲中的最大值是多少。那么我们加入一个点时就可以快速求出第一个大于他的位置在哪里。即nxt[x][0],然后递推可以分别求出nxt[x][1],nxt[x][2].....沿途记录sum即可。

技术分享图片
 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 const int inf=4e5+10;
 5 int Q,siz,last;
 6 int w[inf];
 7 int fa[inf][20],Max[inf][20];
 8 int nxt[inf][20];
 9 LL sum[inf][20];
10 void get(int x,int y){
11     fa[x][0]=y;
12     Max[x][0]=w[y];
13     for(int i=1;i<=19;i++){
14         fa[x][i]=fa[fa[x][i-1]][i-1];
15         Max[x][i]=max(Max[x][i-1],Max[fa[x][i-1]][i-1]);
16     }
17     int now=x;
18     for(int i=19;i>=0;i--){
19         if(Max[now][i]<w[x])now=fa[now][i];
20     }
21     nxt[x][0]=fa[now][0];
22     sum[x][0]=w[fa[now][0]];
23     for(int i=1;i<=19;i++){
24         nxt[x][i]=nxt[nxt[x][i-1]][i-1];
25         sum[x][i]=sum[x][i-1]+sum[nxt[x][i-1]][i-1];
26     }
27 }
28 int p[20];
29 int work(int x,LL y){
30     if(w[x]>y)return 0;
31     int cnt=1;
32     y-=w[x];
33     for(int i=19;i>=0;i--){
34         if(nxt[x][i]!=0&&sum[x][i]<=y){
35             y-=sum[x][i];
36             x=nxt[x][i];
37             cnt+=p[i];
38         }
39     }
40     return cnt;
41 }
42 int main()
43 {
44     scanf("%d",&Q);
45     siz=1;
46     p[0]=1;
47     for(int i=1;i<=19;i++)p[i]=p[i-1]<<1;
48     while(Q--){
49         int opt;
50         LL x,y;
51         scanf("%d%lld%lld",&opt,&x,&y);
52         x=x^last;y=y^last;
53         if(opt==1){
54             siz++;
55             w[siz]=y;
56             get(siz,x);
57         }
58         else {
59             last=work(x,y);
60             printf("%d\n",last);
61         }
62     }
63     return 0;
64 }
View Code

 

ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) ---d

标签:namespace   eve   codeforce   get   splay   div   i++   closed   --   

原文地址:https://www.cnblogs.com/hyghb/p/8456335.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!