• P3261 [JLOI2015]城池攻占


    思路

    左偏树维护每个骑士的战斗力和加入的深度(因为只能向上跳)
    注意做乘法的时候加法tag会受到影响

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long 
    using namespace std;
    struct Node{
    	int lson,rson,dis,num,mul,add,add_dep,sz,fa,id;
    }LT[300100];
    int n,m,u[300100<<1],v[300100<<1],fir[300100],nxt[300100<<1],cnt,fa[300100],S[300100],C[300100],A[300100],V[300100],H[300100],root[300100],ans_city[300100],ans_man[300100],dep[300100];
    int find(int x){
    	if(LT[x].fa==x)
    		return x;
    	else 
    		return LT[x].fa=find(LT[x].fa);
    }
    void pushup(int o){
    	LT[o].sz=LT[LT[o].lson].sz+LT[LT[o].rson].sz+1;
    }
    void pushdown(int o){
    	if(LT[o].mul!=1){
    		LT[LT[o].lson].num*=LT[o].mul;
    		LT[LT[o].rson].num*=LT[o].mul;
    		LT[LT[o].lson].mul*=LT[o].mul;
    		LT[LT[o].rson].mul*=LT[o].mul;
    		LT[LT[o].lson].add*=LT[o].mul;
    		LT[LT[o].rson].add*=LT[o].mul;
    		LT[o].mul=1;
    	} 
    	if(LT[o].add){
    		LT[LT[o].lson].num+=LT[o].add;
    		LT[LT[o].rson].num+=LT[o].add;
    		LT[LT[o].lson].add+=LT[o].add;
    		LT[LT[o].rson].add+=LT[o].add;
    		LT[o].add=0;
    	}
    }
    int merge(int x,int y){
    	if(x*y==0)
    		return x+y;
    	pushdown(x);
    	pushdown(y);
    	if(LT[x].num>LT[y].num)
    		swap(x,y);
    	LT[x].rson=merge(LT[x].rson,y);
    	if(LT[LT[x].lson].dis<LT[LT[x].rson].dis)
    		swap(LT[x].lson,LT[x].rson);
    	LT[x].dis=LT[LT[x].rson].dis+1;
    	LT[LT[x].lson].fa=LT[LT[x].rson].fa=LT[x].fa=x;
    	pushup(x); 
    	return x;
    }
    int pop(int u){
    	pushdown(u); 
    	LT[LT[u].lson].fa=LT[u].lson;
    	LT[LT[u].rson].fa=LT[u].rson; 
    	return LT[u].fa=merge(LT[u].lson,LT[u].rson);
    }
    void addedge(int ui,int vi){
    	++cnt;
    	u[cnt]=ui;
    	v[cnt]=vi;
    	nxt[cnt]=fir[ui];
    	fir[ui]=cnt;
    }
    void dfs_dep(int u){
    	dep[u]=dep[fa[u]]+1;
    	for(int i=fir[u];i;i=nxt[i]){
    		if(v[i]==fa[u])
    			continue;
    		dfs_dep(v[i]); 
    	}
    }
    void dfs(int u){
    	for(int i=fir[u];i;i=nxt[i]){
    		if(v[i]==fa[u])
    			continue;
    		dfs(v[i]); 
    		root[u]=merge(root[u],root[v[i]]);
    	}	
    	while(LT[root[u]].sz>=1&&LT[root[u]].num<H[u]){
    		ans_city[u]++;
    		ans_man[LT[root[u]].id]=LT[root[u]].add_dep-dep[u];
    		root[u]=pop(root[u]);
    	}
    	if(A[u]){
    		LT[root[u]].num*=V[u];
    		LT[root[u]].mul*=V[u];
    		LT[root[u]].add*=V[u];		
    	}
    	else {
    		LT[root[u]].num+=V[u];
    		LT[root[u]].add+=V[u];	
    	}
    }
    void init(void){
    	for(int i=1;i<=m;i++){
    		LT[i].add_dep=dep[C[i]];
    		LT[i].add=0;
    		LT[i].mul=1;
    		LT[i].id=i;
    		LT[i].dis=1;
    		LT[i].sz=1;
    		LT[i].lson=LT[i].rson=0;
    		LT[i].fa=i;
    		LT[i].num=S[i];
    		root[C[i]]=merge(root[C[i]],i);
    	}
    }
    signed main(){
    	scanf("%lld %lld",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&H[i]);
    	}
    	for(int i=2;i<=n;i++){
    		scanf("%lld %lld %lld",&fa[i],&A[i],&V[i]);
    		if(fa[i]){
    			addedge(i,fa[i]);
    			addedge(fa[i],i);
    		}
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%lld %lld",&S[i],&C[i]);
    	} 
    	dfs_dep(1);
    	init();
    	dfs(1);
    	while(LT[root[1]].sz>=1){
    		ans_man[LT[root[1]].id]=LT[root[1]].add_dep;
    		root[1]=pop(root[1]);
    	}
    	for(int i=1;i<=n;i++){
    		printf("%lld
    ",ans_city[i]);
    	}
    	for(int i=1;i<=m;i++) {
    		printf("%lld
    ",ans_man[i]);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    查看JVM使用的默认的垃圾收集器
    生产环境mysql的参数设置不一样,好好的程序,又出错
    伤秦姝行
    《道德经》全文——马王堆出土帛书版
    100篇锻炼口才表达能力的绕口令
    《道德经》部分
    40篇英语短文搞定3500个单词
    python浮点数与整数间的转化
    理解微积分
    matlab判断某个变量是否存在
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10546169.html
Copyright © 2020-2023  润新知