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

    题意

    暴力自然是模拟,考虑优化下模拟的过程。

    我们对每个点开个左偏树,初始为在该点的骑士,之后dfs过程当中从儿子向父亲合并,同时弹出小于当前点的骑士,增加当前点的答。对于每个骑士的答案,我们记录他的起始点和终点即可。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn=300010;
    int n,m,cnt;
    int head[maxn],def[maxn],type[maxn],delta[maxn],ans1[maxn],ans2[maxn],root[maxn],dep[maxn],st[maxn];
    struct edge{int to,nxt;}e[maxn<<1];
    struct Heap
    {
    	#define lc(p) (heap[p].lc)
    	#define rc(p) (heap[p].rc)
    	#define val(p)(heap[p].val)
    	#define dis(p) (heap[p].dis)
    	#define tag1(p) (heap[p].tag1)
    	#define tag2(p) (heap[p].tag2) 
    	int lc,rc;
    	int val,dis,tag1,tag2; 
    }heap[maxn];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    inline void move(int x,int mul,int add)
    {
    	if(!x)return;
    	val(x)*=mul;val(x)+=add;
    	tag1(x)*=mul;tag2(x)*=mul;tag2(x)+=add;
    }
    inline void down(int x)
    {
    	move(lc(x),tag1(x),tag2(x)),move(rc(x),tag1(x),tag2(x));
    	tag1(x)=1,tag2(x)=0;
    }
    int merge(int x,int y)
    {
    	if(!x||!y)return x+y;
    	down(x),down(y);
    	if(val(x)>val(y))swap(x,y);
    	rc(x)=merge(rc(x),y);
    	if(dis(rc(x))>dis(lc(x)))swap(lc(x),rc(x));
    	dis(x)=dis(rc(x))+1;
    	return x;
    }
    void dfs(int x,int pre)
    {
    	dep[x]=dep[pre]+1;
    	for(int i=head[x];i;i=e[i].nxt)if(e[i].to!=pre)dfs(e[i].to,x),root[x]=merge(root[x],root[e[i].to]);
    	while(root[x]&&val(root[x])<def[x])
    	{
    		down(root[x]);
    		ans1[x]++;ans2[root[x]]=dep[st[root[x]]]-dep[x];
    		root[x]=merge(lc(root[x]),rc(root[x]));
    	}
    	if(type[x])move(root[x],delta[x],0);
    	else move(root[x],1,delta[x]);
    }
    signed main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)def[i]=read();
    	for(int i=2;i<=n;i++)
    	{
    		int x=read();add(i,x),add(x,i);
    		type[i]=read(),delta[i]=read();
    	}
    	dis(0)=-1;
    	for(int i=1;i<=m;i++)tag1(i)=1;
    	for(int i=1;i<=m;i++)
    	{
    		int k=read();st[i]=read();
    		val(i)=k;
    		root[st[i]]=merge(root[st[i]],i);
    	}
    	dfs(1,0);
    	while(root[1])down(root[1]),ans2[root[1]]=dep[st[root[1]]],root[1]=merge(lc(root[1]),rc(root[1]));
    	for(int i=1;i<=n;i++)printf("%lld
    ",ans1[i]);
    	for(int i=1;i<=m;i++)printf("%lld
    ",ans2[i]);
    	return 0;
    }
    
  • 相关阅读:
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    64位WIN7系统 下 搭建Android开发环境
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
  • 原文地址:https://www.cnblogs.com/nofind/p/11984747.html
Copyright © 2011-2022 走看看