• 【洛谷P1486】郁闷的出纳员【Treap】


    题目大意:

    题目链接:https://www.luogu.org/problem/P1486
    你需要维护一下四个操作:

    • I kI k:插入一个数字kk
    • A kA k:将所有数字增加kk
    • S kS k:将所有数字减去kk
    • F kF k:查询第kk大的数字。

    注意如果一个数字小于minmin,那么就要把这个数字删除。


    思路:

    依然算是一道TreapTreap的模板题,菜到已经只会敲模板了啊。
    我们发现这里的修改操作全部都是对于所有数的,所以我们不用修改所有的数字,只要记录一个sumsum表示修改的值即可。
    但是注意这样的话新加入的数字应该为ksumk-sum,因为我们定义每一个数字为k+sumk+sum,但是新加入的数字是不会被前面的修改操作影响的。所以减去sumsum之后,这个数字就是(ksum)+sum=k(k-sum)+sum=k
    插入操作就是普通的插入操作。直接套模板就好了。
    然后修改操作我们只需要把sumsum更改就行了。但是注意我们在进行SS操作时要考虑会影响到部分数字会被删除。
    因为每一个数字都加上sumsum,那么对于数字xx,如果x+sum<minx+sum<min,那么xx就要被删除。也就是说,TreapTreap中所有小于minsummin-sum的数字都要被删除。
    由于修改操作很少,所以我们可以考虑暴力修改。先求出val=minsumval=min-sum的前驱,删除该前驱后再求val=pre(val)val'=pre(val),删除valval',以此类推,直到valvalleq -infty为止。
    查询操作也是最基本的查询操作。但是注意查询的是第kk大,而不是第kk小。
    总体来说还是很裸的,但是就是这样一道裸题都卡了我2天,不想说什么了。


    代码:

    #include <ctime>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=600010,Inf=2e9;
    int n,minn,sum,root,tot,k,leave;
    char ch;
    bool flag;
    
    struct treenode
    {
    	int lc,rc,dat,cnt,size,val;
    };
    
    struct Treap
    {
    	treenode t[N];
    	
    	int New(int val)
    	{
    		t[++tot].val=val;
    		t[tot].dat=rand();
    		t[tot].cnt=t[tot].size=1;
    		return tot;
    	}
    	
    	void update(int x)
    	{
    		t[x].size=t[t[x].lc].size+t[t[x].rc].size+t[x].cnt;
    	}
    	
    	void build()
    	{
    		root=New(-Inf);
    		t[1].rc=New(Inf);
    		update(1);
    	}
    	
    	void zig(int &x)
    	{
    		int y=t[x].lc;
    		t[x].lc=t[y].rc; t[y].rc=x; x=y;
    		update(t[x].rc); update(x);
    	}
    	
    	void zag(int &x)
    	{
    		int y=t[x].rc;
    		t[x].rc=t[y].lc; t[y].lc=x; x=y;
    		update(t[x].lc); update(x);
    	}
    	
    	void insert(int &x,int val)
    	{
    		if (!x)
    		{
    			x=New(val);
    			return;
    		}
    		if (t[x].val==val)
    		{
    			t[x].cnt++;
    			update(x);
    			return;
    		}
    		if (val<t[x].val)
    		{
    			insert(t[x].lc,val);
    			if (t[x].dat<t[t[x].lc].dat) zig(x);
    		}
    		else
    		{
    			insert(t[x].rc,val);
    			if (t[x].dat<t[t[x].rc].dat) zag(x);
    		}
    		update(x);
    	}
    	
    	void del(int &x,int val)
    	{
    		if (!x) return;
    		if (t[x].val==val)
    		{
    			if (t[x].cnt>0)
    			{
    				leave+=t[x].cnt;
    				t[x].cnt=0;
    				//update(x);
    			}
    			if (t[x].lc || t[x].rc)
    			{
    				if (!t[x].lc || t[t[x].rc].dat>t[t[x].lc].dat)
    					zag(x),del(t[x].lc,val);
    				else
    					zig(x),del(t[x].rc,val);
    				update(x);
    			}
    			else x=0;
    			return;
    		}
    		if (val<t[x].val) del(t[x].lc,val);
    			else del(t[x].rc,val);
    		update(x);
    	}
    	
    	int get_val(int x,int rank)
    	{
    		if (!x)
    		{
    			flag=0;
    			return Inf;
    		}
    		if (t[t[x].rc].size+1<=rank && t[t[x].rc].size+t[x].cnt>=rank)
    			return t[x].val;
    		if (rank<=t[t[x].rc].size) return get_val(t[x].rc,rank);
    			else return get_val(t[x].lc,rank-t[t[x].rc].size-t[x].cnt);
    	}
    	
    	int pre(int x,int val)
    	{
    		if (!x) return -Inf;
    		if (t[x].val<val) return max(t[x].val,pre(t[x].rc,val));
    			else return pre(t[x].lc,val);
    	}
    }Treap;
    
    int main()
    {
    	scanf("%d%d",&n,&minn);
    	srand(time(0));
    	Treap.build();
    	while (n--)
    	{
    		while (ch=getchar()) if (ch>='A'&&ch<='Z') break;
    		scanf("%d",&k);
    		if (ch=='I')
    		{
    			k-=sum;
    			if (k+sum>=minn) Treap.insert(root,k);
    		}
    		if (ch=='A') sum+=k;
    		if (ch=='S')
    		{
    			sum-=k;
    			int val=Treap.pre(root,minn-sum);
    			while (val>-Inf)
    			{
    				Treap.del(root,val);
    				val=Treap.pre(root,val);
    			}
    		}
    		if (ch=='F')
    		{
    			flag=1;
    			int ans=Treap.get_val(root,k+1);
    			if (!flag || ans<=-Inf) printf("-1
    ");
    				else printf("%d
    ",ans+sum);
    		}
    	}
    	printf("%d
    ",leave);
    	return 0;
    }
    
  • 相关阅读:
    Android开发学习之路-使用Handler和Message更新UI
    Android开发学习之路-Service和Activity的通信
    Android开发学习之路-自定义ListView(继承BaseAdapter)
    URI、URL、URN
    理解 node.js 的事件循环
    创建hexo风格的markdown页面
    heroku
    js通过沿着作用域链还是原型链查找变量
    浏览器中实现3D全景浏览
    数据可视化图表ECharts
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998083.html
Copyright © 2020-2023  润新知