BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆
https://www.lydsy.com/JudgeOnline/problem.php?id=4003
感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始终保持右边堆的深度比左边堆的小一些以保证复杂度,大概因为这个所以也叫左偏树吧。
这个题我最开始看错题目了所以看板子的时候一头雾水满脑子都是“这个实现有问题吧”,然后又看了一遍题目发现没问题骑士就是往上走的。
这道题是把每个点建一个堆然后从叶子到根向上传递+去掉没法再往上的,复杂度大概是O(nlogn)?
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=300010; 9 long long read(){ 10 long long x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while('0'<=ch&&ch<='9'){ x=x*10+ch-'0';ch=getchar(); } 13 return x*f; 14 } 15 int n,m; 16 long long h[maxn]={},k[maxn]={},b[maxn]={},s[maxn]={}; 17 int fa[maxn]={},c[maxn]={}; 18 int rt[maxn]={},ans1[maxn]={},ans2[maxn]={}; 19 struct use{ int y,next; }e[maxn]; 20 int head[maxn]={},dep[maxn]={},tot=0; 21 struct hp{ long long k,b,v; int dis,l,r; }t[maxn]; 22 void init(int x,int y){ 23 e[++tot].y=y;e[tot].next=head[x];head[x]=tot; 24 } 25 inline void Ad(int x,long long tk,long long tb){ 26 t[x].k*=tk; 27 t[x].b=t[x].b*tk+tb; 28 t[x].v=t[x].v*tk+tb; 29 } 30 inline void downdata(int x){ 31 if(t[x].l)Ad(t[x].l,t[x].k,t[x].b);; 32 if(t[x].r)Ad(t[x].r,t[x].k,t[x].b); 33 t[x].k=1;t[x].b=0; 34 } 35 int merge(int x,int y){ 36 if(!x)return y;if(!y)return x; 37 downdata(x);downdata(y); 38 if(t[x].v>t[y].v)swap(x,y); 39 t[x].r=merge(t[x].r,y); 40 if(t[t[x].r].dis>t[t[x].l].dis)swap(t[x].r,t[x].l); 41 t[x].dis=t[t[x].r].dis+1; 42 return x; 43 } 44 void dfs(int x){ 45 int y; 46 for(int i=head[x];i;i=e[i].next){ 47 y=e[i].y; 48 dep[y]=dep[x]+1; 49 dfs(y);Ad(rt[y],k[y],b[y]); 50 rt[x]=merge(rt[x],rt[y]); 51 } 52 while(rt[x]&&t[rt[x]].v<h[x]){ 53 downdata(rt[x]);ans1[x]++; 54 ans2[rt[x]]=dep[c[rt[x]]]-dep[x]; 55 rt[x]=merge(t[rt[x]].l,t[rt[x]].r); 56 } 57 } 58 int main(){ 59 n=read();m=read(); 60 for(int i=1;i<=n;i++)h[i]=read(); 61 for(int i=2;i<=n;i++){ 62 fa[i]=read();init(fa[i],i); 63 k[i]=read();b[i]=read(); 64 if(!k[i])k[i]=1; 65 else{k[i]=b[i];b[i]=0;} 66 } 67 for(int i=1;i<=m;i++){ 68 s[i]=read();c[i]=read(); 69 t[i].k=1; t[i].b=0; t[i].v=s[i]; 70 rt[c[i]]=merge(rt[c[i]],i); 71 }dep[1]=1; 72 dfs(1); 73 while(rt[1]){ 74 downdata(rt[1]); 75 ans2[rt[1]]=dep[c[rt[1]]]; 76 rt[1]=merge(t[rt[1]].l,t[rt[1]].r); 77 } 78 for(int i=1;i<=n;i++)printf("%d\n",ans1[i]); 79 for(int i=1;i<=m;i++)printf("%d\n",ans2[i]); 80 return 0; 81 }