好像所有人都写的左偏树 但我不会啊233
首先发现乘的时候 系数不会为负,所以能得到一个关键条件:变化后的战斗力随变化前的战斗力大小单调
所以我们考虑倍增
设hp[x][i]是从x开始一路攻克$2^i$个城池所需要最小的初始生命值
设trans[x][i][0/1]是攻克了$2^i$个城池后攻击力的变化量,0表示乘,1表示加,先乘后加
然后就可以倍增了
1 #include<bits/stdc++.h> 2 #define pa pair<ll,ll> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 const int maxn=3e5+5; 8 9 inline char gc(){ 10 return getchar(); 11 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++; 13 } 14 inline ll rd(){ 15 ll x=0;char c=gc();bool neg=0; 16 while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();} 17 while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc(); 18 return neg?(~x+1):x; 19 } 20 21 int N,M,fa[maxn][21]; 22 ll hp[maxn][21],trans[maxn][21][2]; 23 int ans1[maxn],ans2[maxn]; 24 25 int main(){ 26 //freopen("","r",stdin); 27 int i,j,k; 28 N=rd(),M=rd(); 29 for(i=1;i<=N;i++) hp[i][0]=rd(); 30 fa[1][0]=N+1; 31 for(i=2;i<=N;i++){ 32 fa[i][0]=rd(); 33 ll x=rd(),y=rd(); 34 trans[i][0][0]=1; 35 trans[i][0][!x]=y; 36 for(j=0;fa[i][j]&&fa[fa[i][j]][j];j++){ 37 fa[i][j+1]=fa[fa[i][j]][j]; 38 hp[i][j+1]=max(hp[i][j],(ll)ceil(1.0*(hp[fa[i][j]][j]-trans[i][j][1])/trans[i][j][0])); 39 trans[i][j+1][1]=trans[i][j][1]*trans[fa[i][j]][j][0]+trans[fa[i][j]][j][1]; 40 trans[i][j+1][0]=trans[i][j][0]*trans[fa[i][j]][j][0]; 41 } 42 } 43 for(i=1;i<=M;i++){ 44 ll s=rd();int x=rd(),n=0; 45 for(j=20;j>=0&&x!=-1;j--){ 46 if(fa[x][j]&&hp[x][j]<=s){ 47 s=s*trans[x][j][0]+trans[x][j][1]; 48 x=fa[x][j]; 49 n+=1<<j; 50 } 51 } 52 if(x!=-1) ans1[x]++; 53 ans2[i]=n; 54 } 55 for(i=1;i<=N;i++) 56 printf("%d ",ans1[i]); 57 for(i=1;i<=M;i++) 58 printf("%d ",ans2[i]); 59 60 return 0; 61 }
然而空间大小恶意卡倍增
但是我们这个倍增可以换成三进制的2333
就是把定义里的$2^i$都换成$3^i$
于是$log_3300000=10$,空间就变成了原来的一半
需要注意的一点是,最后在跳倍增的时候,同一个长度可以跳两次(因为是三进制嘛),循环的时候稍微注意一下
1 #include<bits/stdc++.h> 2 #define pa pair<ll,ll> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 #define MP make_pair 5 using namespace std; 6 typedef long long ll; 7 const int maxn=3e5+5; 8 9 inline char gc(){ 10 return getchar(); 11 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 12 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++; 13 } 14 inline ll rd(){ 15 ll x=0;char c=gc();bool neg=0; 16 while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();} 17 while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc(); 18 return neg?(~x+1):x; 19 } 20 21 int N,M,fa[maxn][11]; 22 ll hp[maxn][11],trans[maxn][11][2]; 23 int ans1[maxn],ans2[maxn]; 24 int pw3[11]; 25 26 int main(){ 27 //freopen("","r",stdin); 28 int i,j,k; 29 pw3[0]=1;for(i=1;i<=10;i++) pw3[i]=pw3[i-1]*3; 30 N=rd(),M=rd(); 31 for(i=1;i<=N;i++) hp[i][0]=rd(); 32 fa[1][0]=N+1; 33 for(i=2;i<=N;i++){ 34 fa[i][0]=rd(); 35 ll x=rd(),y=rd(); 36 trans[i][0][0]=1; 37 trans[i][0][!x]=y; 38 for(j=0;j<10;j++){ 39 int f=fa[i][j],ff=fa[f][j]; 40 if(!f||!ff||!fa[ff][j]) break; 41 fa[i][j+1]=fa[ff][j]; 42 ll hp1=max(hp[f][j],(ll)ceil(1.0*(hp[ff][j]-trans[f][j][1])/trans[f][j][0])); 43 hp[i][j+1]=max(hp[i][j],(ll)ceil(1.0*(hp1-trans[i][j][1])/trans[i][j][0])); 44 trans[i][j+1][1]=trans[i][j][1]*trans[f][j][0]+trans[f][j][1]; 45 trans[i][j+1][0]=trans[i][j][0]*trans[f][j][0]; 46 trans[i][j+1][1]=trans[i][j+1][1]*trans[ff][j][0]+trans[ff][j][1]; 47 trans[i][j+1][0]=trans[i][j+1][0]*trans[ff][j][0]; 48 } 49 } 50 for(i=1;i<=M;i++){ 51 ll s=rd();int x=rd(),n=0; 52 for(j=10;j>=0&&x!=-1;j--){ 53 if(fa[x][j]&&hp[x][j]<=s){ 54 s=s*trans[x][j][0]+trans[x][j][1]; 55 x=fa[x][j]; 56 n+=pw3[j];j++; 57 } 58 } 59 if(x!=-1) ans1[x]++; 60 ans2[i]=n; 61 } 62 for(i=1;i<=N;i++) 63 printf("%d ",ans1[i]); 64 for(i=1;i<=M;i++) 65 printf("%d ",ans2[i]); 66 67 return 0; 68 }