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;
}

  

自己还是太辣鸡了
原文地址:https://www.cnblogs.com/zzyer/p/8609661.html