1. 程式人生 > >BZOJ4003 JLOI2015城池攻占

BZOJ4003 JLOI2015城池攻占

const 復雜度 swap style str blog type die while

用左偏樹模擬攻占的過程,維護最小值,最多入和出m次,每次log復雜度。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e5+10;
 4 typedef long long ll;
 5 ll w[N],v[N],mul[N],add[N],h[N];
 6 int l[N],r[N],dis[N],flag[N],c[N],rt[N],head[N],f[N],d[N],die[N],a[N],n,m,cnt;
 7 struct edge
 8 {
 9     int to,nex;
10 }e[N<<1]; 11 void adde(int x,int y) 12 { 13 e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt; 14 } 15 void pushdown(int x) 16 { 17 if(mul[x]>1) 18 { 19 mul[l[x]]*=mul[x];mul[r[x]]*=mul[x]; 20 add[l[x]]*=mul[x];add[r[x]]*=mul[x]; 21 } 22 if(add[x])
23 { 24 add[l[x]]+=add[x];add[r[x]]+=add[x]; 25 } 26 w[l[x]]*=mul[x];w[l[x]]+=add[x]; 27 w[r[x]]*=mul[x];w[r[x]]+=add[x]; 28 mul[x]=1;add[x]=0; 29 } 30 int merge(int x,int y) 31 { 32 if(!x||!y)return x+y; 33 pushdown(x);pushdown(y); 34 if(w[x]>w[y])swap(x,y);
35 r[x]=merge(r[x],y); 36 if(dis[r[x]]>dis[l[x]])swap(l[x],r[x]); 37 dis[x]=dis[r[x]]+1; 38 return x; 39 } 40 void dfs(int x,int fa) 41 { 42 for(int i=head[x];i;i=e[i].nex) 43 { 44 int y=e[i].to; 45 if(y==fa)continue; 46 d[y]=d[x]+1;dfs(y,x);rt[x]=merge(rt[x],rt[y]); 47 } 48 while(rt[x]&&w[rt[x]]<h[x]) 49 { 50 pushdown(rt[x]); 51 die[rt[x]]=d[c[rt[x]]]-d[x]; 52 flag[x]++;rt[x]=merge(l[rt[x]],r[rt[x]]); 53 } 54 if(a[x])mul[rt[x]]*=v[x],add[rt[x]]*=v[x],w[rt[x]]*=v[x],pushdown(rt[x]); 55 else add[rt[x]]+=v[x],w[rt[x]]+=v[x],pushdown(rt[x]); 56 return; 57 } 58 int main() 59 { 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=n;++i)scanf("%lld",&h[i]); 62 for(int i=2;i<=n;++i) 63 { 64 scanf("%d%d%lld",&f[i],&a[i],&v[i]); 65 adde(i,f[i]);adde(f[i],i); 66 } 67 for(int i=1;i<=m;++i) 68 { 69 scanf("%lld%d",&w[i],&c[i]); 70 rt[c[i]]=merge(rt[c[i]],i); 71 mul[i]=1; 72 } 73 d[1]=1;dfs(1,0); 74 while(rt[1])pushdown(rt[1]),die[rt[1]]=d[c[rt[1]]],rt[1]=merge(l[rt[1]],r[rt[1]]); 75 for(int i=1;i<=n;++i)printf("%d\n",flag[i]); 76 for(int i=1;i<=m;++i)printf("%d\n",die[i]); 77 return 0; 78 }

BZOJ4003 JLOI2015城池攻占