• 题解 P1503 【鬼子进村】


    提供两种做法,fhq_treap和set

    思路:

    • 首先在平衡树中加入0节点和n+1节点,是左右边界
    • 'D x':在平衡树中加入x节点(为什么是加入而不是删除,我后面会详细讲到)
    • 'R':既然是上一个点恢复了,而样例的最后一个询问为我们贴心地考虑了连续恢复的情况,那么就是要维护一个后进先出的来保存您删除的点啦~
    • 'Q x'查询x点的前驱pre上一个被删除的点),和x的后继suc下一个被删除的点,那么x能到达的点的个数就是suc-pre-1个(题目给的是一条编号连续的链,那么根据编号来查找个数就很方便啦^ _ ^)

    fhq_treap

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dwn(i,a,b) for(int i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    
    const int N=5e4+10;
    int tot,siz[N],val[N],rnd[N],son[N][2];
    int x,y,n,rt,m;  
    
    inline void upd(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}
    inline int new_node(int x){siz[++tot]=1;val[tot]=x;rnd[tot]=rand();return tot;}
    
    inline void split(int now,int k,int &x,int &y){
    	if(!now)x=y=0;
    	else{
    		if(val[now]<=k)
    			x=now,split(son[now][1],k,son[now][1],y);
    		else
    			y=now,split(son[now][0],k,x,son[now][0]);
    		upd(now);
    	}
    }
    
    inline int merge(int x,int y){
    	if(!x || !y)return x^y;
    	if(rnd[x]<rnd[y]){
    		son[x][1]=merge(son[x][1],y);
    		upd(x);
    		return x;
    	}
    	else{
    		son[y][0]=merge(x,son[y][0]);
    		upd(y);
    		return y;
    	}
    }
    
    int kth(int x,int k){
    	while(1){
    		if(siz[son[x][0]]>=k)
    			x=son[x][0];
    		else if(siz[son[x][0]]+1==k)
    			return x;
    		else 
    			k-=siz[son[x][0]]+1,x=son[x][1];
    	}
    }
    
    int del[N];
    stack<int>s;
    
    int main(){
    	#ifdef WIN32
    	freopen("guizi.txt","r",stdin);  
        #endif
    	srand((unsigned)time(NULL));
        rd(n),rd(m);
        split(rt,0,x,y);
    	rt=merge(merge(x,new_node(0)),y);
        split(rt,(n+1),x,y);
    	rt=merge(merge(x,new_node((n+1))),y);
        rep(i,1,m){
        	char op[3];cin>>op;
    		if(op[0]=='R'){
    			int z=0;
    			int last=s.top();
    			split(rt,last,x,z);
    			split(x,last-1,x,y);
    			y=merge(son[y][0],son[y][1]);
    			rt=merge(merge(x,y),z);
    			s.pop();
    			del[last]=0;
    		}
    		else if(op[0]=='D'){
    			int a;rd(a); 
    			split(rt,a,x,y);
    			rt=merge(merge(x,new_node(a)),y);
    			s.push(a);
    			del[a]=1;
    		}
    		else if(op[0]=='Q'){
    			int a;rd(a);
    			if(del[a]){
    				puts("0");
    				continue;
    			}
    			split(rt,a-1,x,y);
    			int pre=val[kth(x,siz[x])];
    //			printf("%d的前驱为%d
    ",a,pre);
    			rt=merge(x,y);
    			split(rt,a,x,y);
    			int suc=val[kth(y,1)];
    			rt=merge(x,y);
    //			printf("%d的后继为%d
    ",a,suc);
    			printf("%d
    ",suc-pre-1);
    		}
        }
        return 0;
    }
    

    set

    用set真是太太太方便啦

    #include<bits/stdc++.h>
    using namespace std;
    
    template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dwn(i,a,b) for(int i=a;i>=b;--i)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ee(i,u) for(int i=head[u];i;i=e[i].next)
    
    const int M=5e4+10; 
    int q[M],tail,n,m;
    
    set<int> s;
    set<int>:: iterator it;
    stack<int>sta;
    
    int main(){
    	#ifdef WIN32
    	freopen("guizi.txt","r",stdin);  
        #endif
        rd(n),rd(m);
    	s.insert(0);
    	s.insert(n+1);
    	while(m--){
            char c;cin>>c;
            if(c=='D'){
            	int x;rd(x);
            	s.insert(x);
            	sta.push(x);
    		}
            else if(c=='Q'){
                int x;rd(x);
                it=s.lower_bound(x);
                if(*it==x){
                	puts("0");
                	continue;
    			}
                printf("%d
    ",*it-*(--it)-1);
            }
            else if(c=='R'){
            	it=s.find(sta.top());
            	sta.pop();
            	s.erase(it);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Redisson分布式锁学习总结:公平锁 RedissonFairLock#lock 获取锁源码分析
    Redisson分布式锁学习总结:可重入锁 RedissonLock#lock 获取锁源码分析
    Redisson分布式锁学习总结:公平锁 RedissonFairLock#unLock 释放锁源码分析
    npm更改为淘宝镜像
    博客园统计阅读量
    自动下载MarkDown格式会议论文的程序
    修改linux ll 命令的日期显示格式
    Canal 实战 | 第一篇:SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存
    Log4j2 Jndi 漏洞原理解析、复盘
    一个菜鸡技术人员,很另类的总结
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634741.html
Copyright © 2020-2023  润新知