zoukankan      html  css  js  c++  java
  • 【洛谷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;
    }
    
  • 相关阅读:
    trackr: An AngularJS app with a Java 8 backend – Part III
    trackr: An AngularJS app with a Java 8 backend – Part II
    21. Wireless tools (无线工具 5个)
    20. Web proxies (网页代理 4个)
    19. Rootkit detectors (隐形工具包检测器 5个)
    18. Fuzzers (模糊测试器 4个)
    16. Antimalware (反病毒 3个)
    17. Debuggers (调试器 5个)
    15. Password auditing (密码审核 12个)
    14. Encryption tools (加密工具 8个)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998083.html
Copyright © 2011-2022 走看看