• 【BZOJ2333】棘手的操作(左偏树,STL)


    【BZOJ2333】棘手的操作(左偏树,STL)

    题面

    BZOJ上看把。。。

    题解

    正如这题的题号
    我只能(2333)
    神TM棘手的题目。。。

    前面的单点/联通块操作
    很显然是一个左偏树+标记
    (确实很显然,只是写死人。。。)

    然后对于全局的最大值而言
    搞一个(multi)来水

    看起来真的简单。。
    写起来真的想死。。。
    记住:要特判一下已经联通的块就不要再去(Merge)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 300010
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int n;
    multiset<int> S;
    struct Node
    {
    	int ls,rs,ff;
    	int v,dis;
    	int lz;
    }t[MAX];
    int Lazy,root;
    int getf(int x){while(t[x].ff)x=t[x].ff;return x;}
    void putlazy(int x,int w)
    {
    	t[x].v+=w;
    	t[x].lz+=w;
    }
    void pushdown(int x)
    {
    	if(!t[x].lz)return;
    	if(t[x].ls)putlazy(t[x].ls,t[x].lz);
    	if(t[x].rs)putlazy(t[x].rs,t[x].lz);
    	t[x].lz=0;
    }
    int Merge(int r1,int r2)
    {
    	if(!r1||!r2)return r1+r2;
    	pushdown(r1);pushdown(r2);
    	if(t[r1].v<t[r2].v)swap(r1,r2);
    	t[r1].rs=Merge(t[r1].rs,r2);
    	t[t[r1].rs].ff=r1;
    	if(t[t[r1].ls].dis<t[t[r1].rs].dis)swap(t[r1].ls,t[r1].rs);
    	t[r1].dis=t[t[r1].rs].dis+1;
    	return r1;
    }
    void Update(int x)
    {
    	if(!x)return;
    	if(t[t[x].ls].dis<t[t[x].rs].dis)swap(t[x].ls,t[x].rs);
    	t[x].dis=t[t[x].rs].dis+1;
    	Update(t[x].ff);
    }
    void Alldown(int x)
    {
    	if(t[x].ff)Alldown(t[x].ff);
    	pushdown(x);
    }
    void Del(int x)
    {
    	Alldown(x);
    	t[t[x].ls].ff=t[t[x].rs].ff=0;
    	if(t[t[x].ff].rs==x)t[t[x].ff].rs=0;
    	else t[t[x].ff].ls=0;
    	int rtt=getf(t[x].ff);
    	Merge(rtt,Merge(t[x].ls,t[x].rs));
    	Update(t[x].ff);
    	t[x].ff=t[x].ls=t[x].rs=0;
    }
    void Plus(int x,int w)//单点修改
    {
    	int rtt=getf(x);
    	if(!t[x].ff)
    	{
    		S.erase(S.find(t[x].v));
    		t[t[x].ls].ff=t[t[x].rs].ff=0;
    		pushdown(x),rtt=Merge(t[x].ls,t[x].rs);
    		t[x].ff=t[x].ls=t[x].rs=0;
    	}
    	else Del(x),S.erase(S.find(t[rtt].v));
    	t[x].v+=w;
    	int gg=Merge(x,rtt);
    	S.insert(t[gg].v);
    }
    void AllPlus(int x,int w)
    {
    	x=getf(x);
    	S.erase(S.find(t[x].v));
    	putlazy(x,w);
    	S.insert(t[x].v);
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)t[i].v=read(),S.insert(t[i].v);
    	int Q=read();
    	char ch[5];
    	while(Q--)
    	{
    		scanf("%s",ch);
    		if(ch[0]=='A')
    		{
    			if(ch[1]=='1')
    			{
    				int x=read(),v=read();
    				Plus(x,v);
    			}
    			else if(ch[1]=='2')
    			{
    				int x=read(),v=read();
    				AllPlus(x,v);
    			}
    			else Lazy+=read();
    		}
    		else if(ch[0]=='F')
    		{
    			if(ch[1]=='1')
    			{
    				int x=read();
    				Alldown(x);
    				printf("%d
    ",t[x].v+Lazy);
    			}
    			else if(ch[1]=='2')
    			{
    				int x=read();
    				x=getf(x);
    				printf("%d
    ",t[x].v+Lazy);
    			}
    			else printf("%d
    ",*--S.end()+Lazy);
    		}
    		else
    		{
    			int x=read(),y=read();
    			x=getf(x),y=getf(y);
    			if(x==y)continue;
    			int kk=Merge(x,y);
    			S.erase(S.find(kk==x?t[y].v:t[x].v));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    解决:安装SQl 2008为SQL Server代理服务提供的凭据无效
    jquery 瀑布流效果
    设置swfupload 一次只上传一个文件
    设置swfupload选择文件后不自动上传
    Sublime Text3 & MinGW & LLVM CLang 安装配置CC++编译环境
    在WINDOWS中安装使用SIGPACK(MinGW64+Sublime Text3 &Visual Studio)
    关于ThinkPHP_5 的入口文件
    centos7安装lamp环境
    ThinPHP_5的请求和响应
    MySQL的字段长度和显示宽度
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8277622.html
Copyright © 2020-2023  润新知