zoukankan      html  css  js  c++  java
  • BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆

    题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值

    考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣。

    每一个节点暴力重建一定不行。我们考虑可并数据结构。每一个节点将子节点的信息直接合并就可以

    能够用启示式合并的Treap。也能够用可并堆

    今天特意去学了这玩应0.0 先写了左偏树 然后又写了下随机堆…… 后者速度上更快一些 只是建议从左偏树開始学起

    总之平衡树常数各种大就是了0.0


    Treap+启示式合并

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 100100
    using namespace std;
    typedef long long ll;
    struct abcd{
    	abcd *ls,*rs;
    	int key;
    	int cnt,siz;
    	ll num,sum;
    	abcd (ll x,int y);
    	void Maintain();
    }*null=new abcd(0,0),*tree[M];
    struct edge{
    	int to,next;
    }table[M];
    int head[M],tot;
    int n,root;
    ll m,ans,leadership[M];
    void Add(int x,int y)
    {
    	table[++tot].to=y;
    	table[tot].next=head[x];
    	head[x]=tot;
    }
    abcd :: abcd(ll x,int y)
    {
    	ls=rs=null;
    	sum=x*y;
    	num=x;
    	cnt=siz=y;
    	key=y?rand():0;
    }
    void abcd :: Maintain()
    {
    	siz=ls->siz+rs->siz+cnt;
    	sum=ls->sum+rs->sum+num*cnt;
    }
    void Zig(abcd *&x)
    {
    	abcd *y=x->ls;
    	x->ls=y->rs;
    	y->rs=x;
    	x=y;
    	x->rs->Maintain();
    }
    void Zag(abcd *&x)
    {
    	abcd *y=x->rs;
    	x->rs=y->ls;
    	y->ls=x;
    	x=y;
    	x->ls->Maintain();
    }
    void Insert(abcd *&x,ll y,int z)
    {
    	if(x==null)
    	{
    		x=new abcd(y,z);
    		return ;
    	}
    	if(y==x->num)
    		x->cnt+=z;
    	else if(y<x->num)
    	{
    		Insert(x->ls,y,z);
    		if(x->ls->key>x->key)
    			Zig(x);
    	}
    	else
    	{
    		Insert(x->rs,y,z);
    		if(x->rs->key>x->key)
    			Zag(x);
    	}
    	x->Maintain();
    }
    int Query(abcd *x,ll y)
    {
    	if(x==null)
    		return 0;
    	ll temp=x->ls->sum;int re=0;
    	if(y<=temp)	return Query(x->ls,y);
    	re+=x->ls->siz;y-=temp;
    	if(y<=x->num*x->cnt)
    		return re+y/x->num;
    	re+=x->cnt;y-=x->num*x->cnt;
    	return re+Query(x->rs,y);
    }
    void Decomposition(abcd *&x,int y)
    {
    	if(x==null)
    		return ;
    	Decomposition(x->ls,y);
    	Decomposition(x->rs,y);
    	Insert(tree[y],x->num,x->cnt);
    	delete x;
    	x=null;
    }
    void Tree_DP(int x)
    {
    	int i;
    	for(i=head[x];i;i=table[i].next)
    	{
    		Tree_DP(table[i].to);
    		if(tree[x]->siz<tree[table[i].to]->siz)
    			swap(tree[x],tree[table[i].to]);
    		Decomposition(tree[table[i].to],x);
    	}
    	ans=max(ans,leadership[x]*Query(tree[x],m));
    }
    int main()
    {
    	
    	//freopen("2809.in","r",stdin);
    	//freopen("2809.out","w",stdout);
    	
    	int i,fa;
    	ll x;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%lld%lld",&fa,&x,&leadership[i]);
    		if(!fa) root=i;
    		else Add(fa,i);
    		tree[i]=new abcd(x,1);
    	}
    	Tree_DP(root);
    	cout<<ans<<endl;
    }
    //lld!!
    

    左偏树

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 100100
    using namespace std;
    struct abcd{
    	abcd *ls,*rs;
    	int num,h;
    	abcd(int x); 
    }*null=new abcd(0),*tree[M];
    struct edge{
    	int to,next;
    }table[M];
    int head[M],tot;
    int n,m,root,leadership[M],sum[M],size[M];
    long long ans;
    void Add(int x,int y)
    {
    	table[++tot].to=y;
    	table[tot].next=head[x];
    	head[x]=tot;
    }
    abcd :: abcd(int x)
    {
    	ls=rs=null;
    	num=x;
    	if(x) h=0;
    	else h=-1;
    }
    abcd* Merge(abcd *x,abcd *y)
    {
    	if(x==null) return y;
    	if(y==null) return x;
    	if(x->num<y->num)
    		swap(x,y);
    	x->rs=Merge(x->rs,y);
    	if(x->ls->h<x->rs->h)
    		swap(x->ls,x->rs);
    	x->h=x->rs->h+1;
    	return x;
    }
    void Tree_DP(int x)
    {
    	int i;
    	for(i=head[x];i;i=table[i].next)
    	{
    		Tree_DP(table[i].to);
    		tree[x]=Merge(tree[x],tree[table[i].to]);
    		sum[x]+=sum[table[i].to];
    		size[x]+=size[table[i].to];
    		while(sum[x]>m)
    		{
    			sum[x]-=tree[x]->num;
    			--size[x];
    			tree[x]=Merge(tree[x]->ls,tree[x]->rs);
    		}
    	}
    	ans=max(ans,(long long)size[x]*leadership[x]);
    }
    int main()
    {
    	int i,fa,x;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%d%d",&fa,&x,&leadership[i]);
    		if(!fa) root=i;
    		else Add(fa,i);
    		tree[i]=new abcd(x);
    		sum[i]=x;
    		size[i]=1;
    	}
    	Tree_DP(root);
    	cout<<ans<<endl;
    }
    

    随机堆
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define M 100100
    using namespace std;
    struct abcd{
    	abcd *ls,*rs;
    	int num;
    	abcd(int x); 
    }*null=new abcd(0),*tree[M];
    struct edge{
    	int to,next;
    }table[M];
    bool son;
    int head[M],tot;
    int n,m,root,leadership[M],sum[M],size[M];
    long long ans;
    void Add(int x,int y)
    {
    	table[++tot].to=y;
    	table[tot].next=head[x];
    	head[x]=tot;
    }
    abcd :: abcd(int x)
    {
    	ls=rs=null;
    	num=x;
    }
    abcd* Merge(abcd *x,abcd *y)
    {
    	if(x==null) return y;
    	if(y==null) return x;
    	if(x->num<y->num)
    		swap(x,y);
    	if(son^=1)
    		x->rs=Merge(x->rs,y);
    	else
    		x->ls=Merge(x->ls,y);
    	return x;
    }
    void Tree_DP(int x)
    {
    	int i;
    	for(i=head[x];i;i=table[i].next)
    	{
    		Tree_DP(table[i].to);
    		tree[x]=Merge(tree[x],tree[table[i].to]);
    		sum[x]+=sum[table[i].to];
    		size[x]+=size[table[i].to];
    		while(sum[x]>m)
    		{
    			sum[x]-=tree[x]->num;
    			--size[x];
    			tree[x]=Merge(tree[x]->ls,tree[x]->rs);
    		}
    	}
    	ans=max(ans,(long long)size[x]*leadership[x]);
    }
    int main()
    {
    	int i,fa,x;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%d%d",&fa,&x,&leadership[i]);
    		if(!fa) root=i;
    		else Add(fa,i);
    		tree[i]=new abcd(x);
    		sum[i]=x;
    		size[i]=1;
    	}
    	Tree_DP(root);
    	cout<<ans<<endl;
    }
    

  • 相关阅读:
    向局域网共享文件夹 写文件(示例)
    安装adb之后出现 找不到设备的情况
    .net 下发送calendar
    解决api 跨域 webconfig添加节点
    String类为什么是不可变的
    Sql
    2020职业规划
    摘录
    Docker
    软件测试工程师的职责是什么
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5111397.html
Copyright © 2011-2022 走看看