JLOI2015 城池攻占
首先一条链的数据我们可以用堆自下而上维护还活首的骑士,判断攻击力最小的能否攻破,能则给堆打整体标记
由链推广到树,我们把堆变成可并堆即可
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<vector> using namespace std; typedef long long ll; vector<int> v[300011]; struct node{ node *ls; node *rs; ll val,mul,add; int dist,peo; node(){ ls=rs=NULL; mul=1;add=0; val=0;dist=0; peo=0; } }; node *root[300011]; int que[300011],g[300011],next[300011],y[300011],f[300011],a[300011]; ll vs[300011],h[300011],atk[300011]; int st[300011],dep[300011],ciy[300011],scr[300011]; int n,m,tt,i; void star(int i,int j) { tt++; next[tt]=g[i]; g[i]=tt; y[tt]=j; } void bfs() { int l,r,x,j,k; l=r=1; que[l]=1; dep[1]=1; while(l<=r){ x=que[l]; j=g[x]; while(j!=0){ k=y[j]; r++; que[r]=k; dep[k]=dep[x]+1; j=next[j]; } l++; } } void change(node *&a,ll x,ll z) { if(z!=1){ a->val*=z; a->add*=z; a->mul*=z; } if(x){ a->val+=x; a->add+=x; } } void down(node *a) { if(a->mul!=1||a->add!=0){ if(a->ls!=NULL)change(a->ls,a->add,a->mul); if(a->rs!=NULL)change(a->rs,a->add,a->mul); a->mul=1; a->add=0; } } node *Merge(node *a,node *b) { if(a==NULL)return b; if(b==NULL)return a; if(a->val>b->val)swap(a,b); down(a); a->rs=Merge(a->rs,b); if(a->ls==NULL||a->ls->dist<a->rs->dist)swap(a->ls,a->rs); if(a->rs==NULL)a->dist=0; else a->dist=a->rs->dist+1; return a; } void Add(int x) { node *ts; int i; for(i=0;i<v[x].size();i++){ ts=new node(); ts->val=atk[v[x][i]]; ts->peo=v[x][i]; root[x]=Merge(root[x],ts); } } void work() { int i,x,po,j; for(i=n;i>=1;i--){ x=que[i]; Add(x); for(j=g[x];j;j=next[j])root[x]=Merge(root[x],root[y[j]]); while(root[x]!=NULL){ if(root[x]->val<h[x]){ scr[x]++; po=root[x]->peo; ciy[po]=dep[st[po]]-dep[x]; down(root[x]); root[x]=Merge(root[x]->ls,root[x]->rs); } else break; } if(root[x]!=NULL){ if(a[x]==0)change(root[x],vs[x],1); else change(root[x],0,vs[x]); } } while(root[1]!=NULL){ po=root[1]->peo; ciy[po]=dep[st[po]]; root[1]=Merge(root[1]->ls,root[1]->rs); } for(i=1;i<=n;i++)printf("%d\n",scr[i]); for(i=1;i<=m;i++)printf("%d\n",ciy[i]); } int main() { scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%lld",&h[i]); for(i=2;i<=n;i++){ scanf("%d%d%lld",&f[i],&a[i],&vs[i]); star(f[i],i); } for(i=1;i<=m;i++){ scanf("%lld%d",&atk[i],&st[i]); v[st[i]].push_back(i); } bfs(); work(); }