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;
    }
    
  • 相关阅读:
    CF733F
    P4826
    洛谷P2687 & P1108
    CF42A
    洛谷P1858
    CF1428C
    洛谷P4981
    树形DP
    背包六讲(也不知道为啥就是六个 $QwQ$)
    2020
  • 原文地址:https://www.cnblogs.com/nofind/p/11984747.html
Copyright © 2011-2022 走看看