• [bzoj4003][JLOI2015]城池攻占_左偏树


    城池攻占 bzoj-4003 JLOI-2015

        题目大意:一颗n个节点的有根数,m个有初始战斗力的骑士都站在节点上。每一个节点有一个standard,如果这个骑士的战斗力超过了这个门槛,他就会根据城池的奖励增加自己的战斗力。具体地:每一个城池有一个flag和一个val,表示成功到达这个城市的骑士的战斗力会乘上val还是加上val。每个骑士都只会向根节点进攻。输出每个骑士败北的城市编号。如果这个骑士成功到达根节点,输出0。

        注释:$1le n,m le 3cdot 10^5$,$-10^{18}le standard , val , attack le 10^{18}$。保证每一个骑士的atk不大于longlong。

          想法:GXZlegend可并堆例题。和上两道题类似地,我们对于每一个城池维护一个小根堆,元素是是当前节点为子树里的骑士到达这里的atk,我们自底向顶修改城墙,顺便将骑士向上推,以及标记的下传。我们在merge函数中完成pushdown的操作。特别地,在维护双标记的时候我默认是先乘后加,所以在pushdown的时候如果发现有乘法标记的话需要先将加法标记扩大,再下传。

        最后,附上丑陋的代码... ...

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 300010
    using namespace std;
    typedef long long ll;
    int head[N],to[N],type[N],next[N],cnt,root[N],l[N],r[N],d[N],deep[N],from[N],kill[N],atk[N];
    ll val[N],h[N],key[N],tadd[N],tmul[N];
    inline void add(int x,int y,int a,ll b)
    {
    	to[++cnt]=y;
    	type[cnt]=a;
    	val[cnt]=b;
    	next[cnt]=head[x];
    	head[x]=cnt;
    }
    inline void pushdown(int x)
    {
    	if(!x)return;
    	if(tmul[x]!=1)
    	{
    		key[l[x]]*=tmul[x];tadd[l[x]]*=tmul[x];tmul[l[x]]*=tmul[x];
    		key[r[x]]*=tmul[x];tadd[r[x]]*=tmul[x];tmul[r[x]]*=tmul[x];
    		tmul[x]=1;
    	}
    	if(tadd[x])
    	{
    		key[l[x]]+=tadd[x];tadd[l[x]]+=tadd[x];
    		key[r[x]]+=tadd[x];tadd[r[x]]+=tadd[x];
    		tadd[x]=0;
    	}
    }
    int merge(int x,int y)
    {
    	if(!x) return y;
    	if(!y) return x;
    	pushdown(x),pushdown(y);
    	if(key[x]>key[y]) swap(x,y);
    	r[x]=merge(r[x],y);
    	if(d[l[x]]<d[r[x]]) swap(l[x],r[x]);
    	d[x]=d[r[x]]+1;
    	return x;
    }
    void dfs(int x)
    {
    	for(int i=head[x];i;i=next[i])
    	{
    		deep[to[i]]=deep[x]+1;
    		dfs(to[i]);
    		if(type[i])
    		{
    			key[root[to[i]]]*=val[i];
    			tadd[root[to[i]]]*=val[i];
    			tmul[root[to[i]]]*=val[i];
    		}
    		else
    		{
    			key[root[to[i]]]+=val[i];
    			tadd[root[to[i]]]+=val[i];
    		}
    		root[x]=merge(root[x],root[to[i]]);
    	}
    	while(root[x]&&key[root[x]]<h[x])
    	{
    		kill[x]++,atk[root[x]]=x,pushdown(root[x]),root[x]=merge(l[root[x]],r[root[x]]);
    	}
    }
    int main()
    {
    	int n,m,x,a;
    	ll b;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
    	for(int i=2;i<=n;i++) scanf("%d%d%lld",&x,&a,&b),add(x,i,a,b);
    	for(int i=1;i<=m;i++)
    	{
    		tmul[i]=1,scanf("%lld%d",&key[i],&from[i]),root[from[i]]=merge(root[from[i]],i);
    	}
    	d[0]=-1,deep[1]=1;
    	dfs(1);
    	for(int i=1;i<=n;i++)
    	{
    		printf("%d
    ",kill[i]);
    	}
    	for(int i=1;i<=m;i++)
    	{
    		printf("%d
    ",deep[from[i]]-deep[atk[i]]);
    	}
    	return 0;
    }
    

        小结:type标记存在哪里都无所谓qwq

      

  • 相关阅读:
    layui弹出层:使用icon图标小结
    layui弹出层:使用icon图标小结
    存储过程分页
    .net 更改GridView标题文字
    PHP文件结尾符的问题
    JAVA中使用JSON进行数据传递
    Ubuntu LAMP环境安装
    PHP中使用class_exists判断类是否存在
    NS_ERROR_XPC_BAD_CONVERT_JS: Could not convert JavaScript argument
    Android开发教程 葵花宝典第六层 控件之 Dialog ListView GridView
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8872352.html
Copyright © 2020-2023  润新知