• 洛谷P3261 [JLOI2015]城池攻占(左偏树)


    传送门

    每一个城市代表的点开一个小根堆,把每一个骑士合并到它开始攻占的城池所代表的点上

    然后开始dfs,每一次把子树里那些还活着的骑士合并上来

    然后再考虑当前点的堆,一直pop直到骑士全死光或者剩下的骑士的攻击力都大于等于当前城池的生命值,同时维护城池和骑士的答案

    然后修改的话在堆顶打一个标记,需要的时候下传即可

     1 //minamoto
     2 #include<bits/stdc++.h>
     3 #define ll long long
     4 using namespace std;
     5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     6 char buf[1<<21],*p1=buf,*p2=buf;
     7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
     8 inline ll read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;ll res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 char sr[1<<21],z[20];int K=-1,Z;
    19 inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
    20 inline void print(int x){
    21     if(K>1<<20)Ot();if(x<0)sr[++K]=45,x=-x;
    22     while(z[++Z]=x%10+48,x/=10);
    23     while(sr[++K]=z[Z],--Z);sr[++K]='
    ';
    24 }
    25 const int N=3e5+5;
    26 int head[N],Next[N],ver[N],tot;
    27 inline void add_edge(int u,int v){
    28     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    29 }
    30 int L[N],R[N],rt[N],d[N],ans1[N],ans2[N],dep[N],c[N],n,m;
    31 ll add[N],mul[N],v[N],h[N],val[N];bool fl[N];
    32 inline void ppd(int p,ll m,ll a){
    33     if(p){
    34         v[p]*=m,v[p]+=a;
    35         mul[p]*=m,add[p]*=m,add[p]+=a;
    36     }
    37 }
    38 inline void pd(int p){
    39     ppd(L[p],mul[p],add[p]),ppd(R[p],mul[p],add[p]);
    40     mul[p]=1,add[p]=0;
    41 }
    42 int merge(int x,int y){
    43     if(!x||!y) return x+y;
    44     pd(x),pd(y);
    45     if(v[x]>v[y]) swap(x,y);
    46     R[x]=merge(R[x],y);
    47     if(d[L[x]]<d[R[x]]) swap(L[x],R[x]);
    48     d[x]=d[R[x]]+1;return x;
    49 }
    50 void dfs(int u,int fa){
    51     dep[u]=dep[fa]+1;
    52     for(int i=head[u];i;i=Next[i]){int v=ver[i];dfs(v,u),rt[u]=merge(rt[u],rt[v]);}
    53     while(rt[u]&&v[rt[u]]<h[u]){
    54         pd(rt[u]);++ans1[u],ans2[rt[u]]=dep[c[rt[u]]]-dep[u];
    55         rt[u]=merge(L[rt[u]],R[rt[u]]);
    56     }
    57     fl[u]?ppd(rt[u],val[u],0):ppd(rt[u],1,val[u]);
    58 }
    59 int main(){
    60 //    freopen("testdata.in","r",stdin);
    61     n=read(),m=read();
    62     for(int i=1;i<=n;++i) h[i]=read();
    63     for(int i=2;i<=n;++i){
    64         int fa=read();fl[i]=read(),val[i]=read();
    65         add_edge(fa,i);
    66     }
    67     for(int i=1;i<=m;++i){
    68         v[i]=read(),c[i]=read();
    69         mul[i]=1;
    70         rt[c[i]]=merge(rt[c[i]],i);
    71     }
    72     dfs(1,0);
    73     while(rt[1]) pd(rt[1]),ans2[rt[1]]=dep[c[rt[1]]],rt[1]=merge(L[rt[1]],R[rt[1]]);
    74     for(int i=1;i<=n;++i) print(ans1[i]);
    75     for(int i=1;i<=m;++i) print(ans2[i]);
    76     Ot();
    77     return 0;
    78 }
  • 相关阅读:
    你所能用到的数据结构(一)
    你所能用到的数据结构(八)
    你所能用到的数据结构(六)
    你所能用到的数据结构(三)
    你所能用到的数据结构(四)
    你所能用到的无损压缩编码(二)
    你所能用到的数据结构(二)
    你所能用到的数据结构(五)
    Attribute在.NET编程中的应用(四)
    对线程安全理解的例子
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9806327.html
Copyright © 2020-2023  润新知