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


    题目大意:维护一个平衡树,支持插入一个数,删除小于一个值的所有数,K 大值查询,每个节点权值加减一个数。

    题解:所有节点权值加减操作可以考虑直接维护一个全局标记,删除小于一个值的所有数字为一个二分的过程,复杂度为 (O(logn)),具体做法为:若当前子树根节点权值小于 X,则直接删除整颗左子树,继续遍历,否则访问左子树。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    
    inline int read(){
    	int x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    
    int n,mi,tag,ans;
    struct node{
    	#define ls(x) t[x].lc
    	#define rs(x) t[x].rc
    	int lc,rc,val,rd,size,cnt;
    }t[maxn];
    int tot,root;
    inline int newnode(int val){
    	++tot,t[tot].val=val,t[tot].rd=rand(),t[tot].size=t[tot].cnt=1;
    	return tot;
    }
    inline void pushup(int o){
    	t[o].size=t[ls(o)].size+t[rs(o)].size+t[o].cnt;
    }
    inline void zig(int &o){
    	int lson=ls(o);
    	ls(o)=rs(lson),rs(lson)=o,o=lson;
    	pushup(rs(o)),pushup(o);
    }
    inline void zag(int &o){
    	int rson=rs(o);
    	rs(o)=ls(rson),ls(rson)=o,o=rson;
    	pushup(ls(o)),pushup(o);
    }
    void insert(int &o,int val){
    	if(!o)o=newnode(val);
    	else if(t[o].val==val)++t[o].cnt,++t[o].size;
    	else if(val<t[o].val){
    		++t[o].size,insert(ls(o),val);
    		if(t[ls(o)].rd>t[o].rd)zig(o);
    	}else{
    		++t[o].size,insert(rs(o),val);
    		if(t[rs(o)].rd>t[o].rd)zag(o);
    	}
    }
    void remove(int &o,int val){
    	if(!o)return;
    	else if(t[o].val>=val)remove(ls(o),val);
    	else{
    		ans+=t[o].cnt+t[ls(o)].size;
    		o=rs(o),remove(o,val);
    	}
    	pushup(o);
    }
    int kth(int o,int k){
    	if(k<=t[ls(o)].size)return kth(ls(o),k);
    	else if(k>t[ls(o)].size+t[o].cnt)return kth(rs(o),k-t[ls(o)].size-t[o].cnt);
    	else return t[o].val;
    }
    
    void solve(){
    	char opt[3];int val;
    	scanf("%d%d",&n,&mi);
    	while(n--){
    		scanf("%s%d",opt,&val);
    		if(opt[0]=='I'){
    			if(val<mi)continue;
    			insert(root,val-tag);
    		}else if(opt[0]=='A')tag+=val;
    		else if(opt[0]=='S'){
    			tag-=val;
    			remove(root,mi-tag);
    		}else{
    			if(val>t[root].size)puts("-1");
    			else printf("%d
    ",kth(root,t[root].size-val+1)+tag);
    		}
    	}
    	printf("%d
    ",ans);
    }
    
    int main(){
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu Linux Matlab 安装 中文乱码 桌面启动器 Could not find the main class: java/splash.png. 终端terminal 直接运行 matlab
    Ubuntu Linux 官网 u盘安装 u盘系统 图文教程
    从google map google earth获得大图 方法总结
    论文查重网址
    [ZZ] Computer Science Conference Rankings
    Ubuntu linux 信使 iptux Window 飞鸽 ipmsg 飞秋 feiq 文件传输
    Ubuntu Linux Matlab mex
    Ubuntu Dell OptiPlex 990 Intel Gigabit CT Desktop Adapter网卡驱动安装
    C++的File类文件操作
    GIS软件比较
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10492582.html
Copyright © 2020-2023  润新知