zoukankan      html  css  js  c++  java
  • 【NOIP2017】列队(Splay)

    【NOIP2017】列队(Splay)

    题面

    洛谷

    题解

    其实好简单啊。。。
    对于每一行维护一棵(Splay)
    对于最后一列维护一棵(Splay)
    (Splay)上一个节点表示一段区间
    每次出去一个人就是把当前的(Splay)的一个节点拆分成(3)

    然后就很简单了。。
    细节比较多。。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 2000000
    #define ls (t[x].ch[0])
    #define rs (t[x].ch[1])
    inline int read()
    {
        RG int x=0,t=1;RG 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;
    }
    struct Node
    {
    	int ch[2],ff;
    	ll size;
    	ll l,r;
    }t[MAX];
    int tot;
    int n,m,Q;
    struct SplayTree
    {
    	int root;
    	int Node(ll l,ll r){++tot;t[tot].l=l;t[tot].r=r;t[tot].size=r-l;return tot;}
    	void pushup(int x){t[x].size=t[ls].size+t[rs].size+t[x].r-t[x].l;}
    	void rotate(int x)
    	{
    		int y=t[x].ff,z=t[y].ff;
    		int k=t[y].ch[1]==x;
    		if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
    		t[y].ch[k]=t[x].ch[k^1];if(t[x].ch[k^1])t[t[x].ch[k^1]].ff=y;
    		t[x].ch[k^1]=y;t[y].ff=x;
    		pushup(y);pushup(x);
    	}
    	void Splay(int x)
    	{
    		for(int y=t[x].ff;y;rotate(x),y=t[x].ff)
    			if(t[y].ff)(rand()&1)?rotate(x):rotate(y);
    		root=x;
    	}
    	int Split(int x,ll K)
    	{
    		K+=t[x].l;
    		int y=Node(K,t[x].r);t[x].r=K;
    		if(!rs)t[y].ff=x,rs=y;
    		else
    		{
    			int u=rs;
    			while(t[u].ch[0])u=t[u].ch[0];
    			t[y].ff=u;t[u].ch[0]=y;
    		}
    		Splay(y);return y;
    	}
    	ll DelKth(ll K)
    	{
    		int x=root;
    		while(2333)
    		{
    			if(K<=t[ls].size)x=ls;
    			else
    			{
    				K-=t[ls].size;
    				if(K<=t[x].r-t[x].l)
    				{
    					if(K<t[x].r-t[x].l)Split(x,K);
    					if(K>1)x=Split(x,K-1);
    					break;
    				}
    				else K-=t[x].r-t[x].l,x=rs;
    			}
    		}
    		Splay(x);t[ls].ff=t[rs].ff=0;
    		if(!ls)root=rs;
    		else
    		{
    			int y=ls;
    			while(t[y].ch[1])y=t[y].ch[1];
    			Splay(y);
    			root=t[t[y].ch[1]=t[x].ch[1]].ff=y;
    			pushup(y);
    		}
    		return t[x].l;
    	}
    	void Insert(ll k)
    	{
    		int y=Node(k,k+1);
    		if(!root)root=y;
    		else
    		{
    			int x=root;
    			while(rs)x=rs;
    			Splay(x);
    			t[rs=y].ff=x;pushup(x);
    		}
    	}
    }Splay[MAX];
    int main()
    {
    	n=read();m=read();Q=read();
    	for(int i=1;i<=n;++i)Splay[i].root=Splay[i].Node(1ll*i*m-m+1,1ll*i*m);
    	for(int i=1;i<=n;++i)Splay[0].Insert(1ll*i*m);
    	while(Q--)
    	{
    		int x=read(),y=read();ll ans;
    		Splay[x].Insert(Splay[0].DelKth(x));
    		printf("%lld
    ",ans=Splay[x].DelKth(y));
    		Splay[0].Insert(ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    剑指 Offer 60. n个骰子的点数
    剑指 Offer 59
    剑指 Offer 59
    剑指 Offer 58
    剑指 Offer 58
    AndroidStudio中提示:Didn't find class "android.support.v7.widget.RecyclerView"
    SpringBoot中通过重写WebMvcConfigurer的addCorsMapping方法实现后台服务解决跨域问题
    Android中使用Room时怎样存储带list集合的对象
    Android中在使用Room时提示:Cannot figure out how to save this field into database. You can consider adding a type converter for
    Android中ListView的使用以及使用适配器设置数据源
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8684116.html
Copyright © 2011-2022 走看看