zoukankan      html  css  js  c++  java
  • BZOJ 4003 [JLOI2015]城池攻占

    题解:

    带标记可并堆

    用可并堆维护可以到某个城池的士兵

    维护小根堆

    堆顶小于h时就弹出来计算

    注意什么时候下放!!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int maxn=300009;
    typedef long long Lint;
    
    int n,m;
    int s[maxn];
    long long h[maxn];
    
    int fa[maxn]={0},ch[maxn][2]={0},dis[maxn]={0};
    long long ky[maxn],tag[maxn],mul[maxn];
    void Putmul(int x,Lint y){
    	ky[x]=ky[x]*y;
    	tag[x]=tag[x]*y;
    	mul[x]=mul[x]*y;
    }
    void Puttag(int x,Lint y){
    	ky[x]=ky[x]+y;
    	tag[x]=tag[x]+y;
    }
    void pushdown(int x){
    	if(mul[x]!=1){
    		if(ch[x][0]){
    			Putmul(ch[x][0],mul[x]);
    		}
    		if(ch[x][1]){
    			Putmul(ch[x][1],mul[x]);
    		}
    		mul[x]=1;
    	}
    	if(tag[x]!=0){
    		if(ch[x][0]){
    			Puttag(ch[x][0],tag[x]);
    		}
    		if(ch[x][1]){
    			Puttag(ch[x][1],tag[x]);
    		}
    		tag[x]=0;
    	}
    }
    int Getf(int x){
    	while(fa[x])x=fa[x];
    	return x;
    }
    int Mer(int x,int y){
    //	pushdown(x);pushdown(y);
    	if((x==0)||(y==0))return x+y;
    	if(ky[x]>ky[y])swap(x,y);
    	pushdown(x);pushdown(y);
    	ch[x][1]=Mer(ch[x][1],y);
    	fa[ch[x][1]]=x;
    	if(dis[ch[x][1]]>dis[ch[x][0]])swap(ch[x][0],ch[x][1]);
    	dis[x]=dis[ch[x][1]]+1;
    	return x;
    }
    
    int rt[maxn]={0};
    int cntedge=0;
    int head[maxn]={0};
    int to[maxn<<1],nex[maxn<<1];
    void Addedge(int x,int y){
    	nex[++cntedge]=head[x];
    	to[cntedge]=y;
    	head[x]=cntedge;
    }
    
    int opty[maxn];
    long long v[maxn];
    int att[maxn],def[maxn]={0};
    int dep[maxn]={0};
    void Dp(int x,int father){
    	dep[x]=dep[father]+1;
    	for(int i=head[x];i;i=nex[i]){
    		Dp(to[i],x);
    		pushdown(rt[x]);pushdown(rt[to[i]]);
    		rt[x]=Mer(rt[x],rt[to[i]]);
    	}
    	while((rt[x])&&(ky[rt[x]]<h[x])){
    		int y=rt[x];
    		att[y]=dep[s[y]]-dep[x];
    		def[x]++;
    		fa[ch[y][0]]=0;
    		fa[ch[y][1]]=0;
    		pushdown(y);
    		rt[x]=Mer(ch[y][0],ch[y][1]);
    	}
    	if(opty[x]==0){
    		Puttag(rt[x],v[x]);
    	}else{
    		Putmul(rt[x],v[x]);
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i)scanf("%lld",&h[i]);
    	for(int i=2;i<=n;++i){
    		int x;scanf("%d",&x);Addedge(x,i);
    		scanf("%d%lld",&opty[i],&v[i]);
    	}
    	for(int i=1;i<=m;++i){
    		scanf("%lld%d",&ky[i],&s[i]);
    		mul[i]=1;
    		rt[s[i]]=Mer(rt[s[i]],i);
    		
    	}
    	Dp(1,0);
    	while(rt[1]){
    		int x=rt[1];
    		att[x]=dep[s[x]];
    		fa[ch[x][0]]=0;
    		fa[ch[x][1]]=0;
    		rt[1]=Mer(ch[x][0],ch[x][1]);
    	}
    	for(int i=1;i<=n;++i){
    		printf("%d
    ",def[i]);
    	}
    	for(int i=1;i<=m;++i){
    		printf("%d
    ",att[i]);
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    查询父节点parentNode
    008-流程控制 case 语句
    007-流程控制 if 语句
    006-条件判断
    005-sort 命令使用
    004-sed 命令使用
    003-awk 命令使用
    002-printf 命令用法
    001-cut 的用法
    002-变量
  • 原文地址:https://www.cnblogs.com/zzyer/p/8609661.html
Copyright © 2011-2022 走看看