• 洛谷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 }
  • 相关阅读:
    centos7配置静态IP地址
    Linux和Windows的区别
    Linux就该这么学——文件的特殊权限
    Linux就该这么学——文件权限与归属
    Linux就该这么学——用户身份与能力
    Linux就该这么学——计划任务服务程序
    Linux就该这么学——流程控制语句
    Linux就该这么学——编写SHELL脚本
    Linux就该这么学——初识vim编辑器
    Linux就该这么学——重要的环境变量
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9806327.html
Copyright © 2020-2023  润新知