1. 程式人生 > >Codefores 932D Tree

Codefores 932D Tree

system through lan can long push_back hash 時間 ide

原題傳送門

一道題意很復雜的題目,為了表達一句話的意思,用了四句話去描述,純粹為了誤導

大致題意:一棵樹,每個結點i會有一個權值weighti,初始時只有一個權值為0的根節點1。給定Q(Q≤4*105)個操作,操作分兩類:

1.1 p q,表示新建結點cnt+1,權值為q,該結點與p結點連邊。

2.2 p q,表示求最長的序列P,滿足P1=p,對i>1,都有:Pi是Pi-1與根結點路徑上離Pi-1最近的權值不小於weighti的點,且所有weightPi加起來(有點拗口,看不懂的可以看原題描述)

具體有一些區別:其實就是強制在線辣,請以實際描述為準。

分析:很明顯能看出一些不變的東西:結點只增不減,而後續結點的加入不會影響之前結點的性質,也就是說,一個結點的信息在他加入的時候就已經完全確定,而這些信息都能由祖先的信息推出,於是想到倍增。具體維護兩個信息st_par和st_sum(我代碼裏省事把st_par簡寫為st,st_sum簡寫為sum),其中st_par[i][j]表示從結點i向上“跳”2j

步的結點編號,這裏“跳”一步指的是進行一次尋找“到根結點路徑上第一個不小於當前結點權值的結點”的操作,st_sum[i][j]表示跳的過程中所有經過結點(不包括起點)的權值之和。能這樣維護的原因是:操作2中的序列其實是唯一的,我只要能快速維護找到下一個結點的操作就行。這樣倍增的輪廓就出來了,但是還有一件事要解決:第一步也就是st[i][0]怎麽計算?這裏就要用到二分的思想了:設tmp為i的父親,利用二分鎖定離i最近的符合要求的點,具體怎麽實現就不用多說了,我想說的是我原本的寫法:我原來寫的是由i的父親一步一步按st[tmp][0]的方式往上跳,實測兩種寫法沒有任何時間上的差別,但是復雜度肯定是不一樣的。。

代碼隨便看看。。

技術分享圖片
  1 /*    Codeforces 932D Tree
  2     1st Edition:2018.2.15 Thursday
  3     2nd Edition:2018.2.16 Friday
  4     Algorithm:倍增
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <algorithm>
  9 #include <cmath>
 10 #include <cstring>
 11 #include <vector>
 12
#include <map> 13 #include <set> 14 #include <bitset> 15 #include <queue> 16 #include <deque> 17 #include <stack> 18 #include <iomanip> 19 #include <cstdlib> 20 #include <ctime> 21 #include <cctype> 22 using namespace std; 23 24 #define is_lower(c) (c>=‘a‘ && c<=‘z‘) 25 #define is_upper(c) (c>=‘A‘ && c<=‘Z‘) 26 #define is_alpha(c) (is_lower(c) || is_upper(c)) 27 #define is_digit(c) (c>=‘0‘ && c<=‘9‘) 28 #define stop system("PAUSE") 29 #define ForG(a,b,c) for(rg int (a)=c.head[b];(a);(a)=c.E[a].nxt) 30 #define For(a,b,c) for(rg int (a)=(b);(a)<=(c);++a) 31 #define min(a,b) ((a)<(b)?(a):(b)) 32 #define max(a,b) ((a)>(b)?(a):(b)) 33 #define shl(x,y) ((x)<<(y)) 34 #define shr(x,y) ((x)>>(y)) 35 #define mp make_pair 36 #define pb push_back 37 #define rg register 38 #ifdef ONLINE_JUDGE 39 #define hash rename_hash 40 #define next rename_next 41 #define prev rename_prev 42 #endif 43 typedef long long ll; 44 typedef unsigned long long ull; 45 typedef pair<int,int> pii; 46 typedef pair<ll,ll> pll; 47 typedef vector<int> vi; 48 typedef double db; 49 const ll inf=1000000007LL; 50 const db EPS=1e-14; 51 const ll inf_ll=(ll)1e18; 52 const ll maxn=400005LL; 53 const ll mod=1000000007LL; 54 55 int n,cnt; 56 ll last; 57 ll weight[maxn],sum[maxn][20]; 58 int par[maxn],st[maxn][20]; 59 60 int main(){ 61 scanf("%d",&n); 62 cnt=1; 63 while(n--){ 64 ll opt,p,q; 65 scanf("%I64d %I64d %I64d",&opt,&p,&q); 66 p^=last;q^=last; 67 if(opt^2){ 68 par[++cnt]=p; 69 weight[cnt]=q; 70 int tmp=p; 71 if(weight[tmp]<q){ 72 for(int i=19;i+1;--i) if(st[tmp][i] && weight[st[tmp][i]]<q){ 73 tmp=st[tmp][i]; 74 } 75 tmp=st[tmp][0]; 76 } 77 st[cnt][0]=tmp; 78 sum[cnt][0]=weight[tmp]; 79 For(i,1,19) if(st[cnt][i-1] && st[st[cnt][i-1]][i-1]){ 80 st[cnt][i]=st[st[cnt][i-1]][i-1]; 81 sum[cnt][i]=sum[cnt][i-1]+sum[st[cnt][i-1]][i-1]; 82 } 83 }else{ 84 ll nowsum=weight[p]; 85 if(nowsum>q){ 86 puts("0"); 87 last=0; 88 continue; 89 } 90 int now=p,res=1; 91 for(int i=19;i>=0;--i) if(st[now][i] && sum[now][i]+nowsum<=q){ 92 nowsum+=sum[now][i]; 93 now=st[now][i]; 94 res+=shl(1,i); 95 } 96 printf("%d\n",res); 97 last=(ll)res; 98 } 99 } 100 return 0; 101 }
View Code

Codefores 932D Tree