BZOJ4003 [JLOI2015] 城池攻占
分析:刚看到题目是有点没方向,(毕竟我这蒟蒻才刚学左偏树)然后看了看别的大佬的博客以后大概懂了,将每个骑士丢进一颗左偏树中,然后进行dfs对每一个城池进行搜索,如果某一个骑士在该城池死亡就将其从弹出并记录。然后过程中下放标记就差不多OK了。具体还是看代码吧。
Code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<iomanip> #include<algorithm> using namespace std; #define ll long long const int N=3e5+7; int n,m,dep[N],head[N],size; int End[N],dead[N],rt[N],beg[N]; ll a[N],v[N],d[N]; struct Knight{ int l,r,dis; ll val,lc,lp; }t[N]; struct Node{ int to,next; }edge[N]; inline ll read() { char ch=getchar();ll num=0;bool flag=false; while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();} while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();} return flag?-num:num; } inline void add(int x,int y) { edge[++size].to=y; edge[size].next=head[x]; head[x]=size; } inline void update(int x,ll mul,ll plu) { if(!x)return; t[x].val*=mul;t[x].val+=plu; t[x].lc*=mul;t[x].lp*=mul;t[x].lp+=plu; } inline void pushdown(int x) { update(t[x].l,t[x].lc,t[x].lp); update(t[x].r,t[x].lc,t[x].lp); t[x].lc=1;t[x].lp=0; } inline int merge(int x,int y) { if(!x||!y)return x+y; pushdown(x);pushdown(y); if(t[x].val>t[y].val||(t[x].val==t[y].val&&x>y)) swap(x,y); int &ur=t[x].r,&ul=t[x].l; ur=merge(ur,y); if(t[ul].dis<t[ur].dis)swap(ur,ul); t[x].dis=t[ur].dis+1; return x; } inline int pop(int x) { return merge(t[x].l,t[x].r); } inline void dfs(int u,int fa) { dep[u]=dep[fa]+1; for(int i=head[u];i!=-1;i=edge[i].next) dfs(edge[i].to,u); for(int i=head[u];i!=-1;i=edge[i].next) rt[u]=merge(rt[u],rt[edge[i].to]); while(rt[u]&&t[rt[u]].val<d[u]){ pushdown(rt[u]); dead[u]+=1; End[rt[u]]=u; rt[u]=pop(rt[u]); } if(!a[u])update(rt[u],1,v[u]); else update(rt[u],v[u],0); } int main() { n=read();m=read(); memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) d[i]=read(); for(int i=2;i<=n;i++){ int ff=read();add(ff,i); a[i]=read();v[i]=read();} for(int i=1;i<=m;i++) t[i].lc=1,t[i].lp=0; for(int i=1;i<=m;i++){ t[i].val=read();beg[i]=read(); rt[beg[i]]=merge(rt[beg[i]],i); } dfs(1,0); for(int i=1;i<=n;i++) printf("%d\n",dead[i]); for(int i=1;i<=m;i++) printf("%d\n",dep[beg[i]]-dep[End[i]]); return 0; }
蒟蒻写博客不易,如果有误还请大佬们提出
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com
如需转载,请署名作者并附上原文链接,蒟蒻非常感激
名称:HolseLee
博客地址:www.cnblogs.com/cytus
个人邮箱:1073133650@qq.com