【题】【线段树(动态开点&负点)】NKOJ 1922 第K小数
2016-07-24 19:33
330 查看
NKOJ 1922 第K小数
时间限制 : 150000 MS 空间限制 : 1655360 KB
问题描述
现在已有N个整数,你有以下三种操作:
A 表示加入一个值为A的整数
B 表示删除其中值为B的整数
K 表示输出这些整数中第K小的数
输入格式
第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作
第二行用空格隔开的N个整数
接下来M行,每行表示一个操作
输出格式
若干行,一行一个整数,表示所求的第K小的数字
样例输入
5 5
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3
样例输出
0
7
提示
注意:如果有多个大小相同的数字,只把他们看做一个数字,如样例。
若找不到第K小的数,输出0
数据范围:
0<=N<=2,000,000
M<=1,000,000
-1,000,000,000<=每个整数<=1,000,000,000
思路:
范围太大,动态建立线段树:每次加入一个数,就将线段树对应叶节点的值改为1,若无该节点就建立;每次减少,对应叶节点改为0;每次查找,先查找左儿子是否有k个数,不足说明该找右儿子。
注意先判断是否存在左右儿子
时间限制 : 150000 MS 空间限制 : 1655360 KB
问题描述
现在已有N个整数,你有以下三种操作:
A 表示加入一个值为A的整数
B 表示删除其中值为B的整数
K 表示输出这些整数中第K小的数
输入格式
第一行,两个整数N,M,表示最开始有N个整数,总共有M个操作
第二行用空格隔开的N个整数
接下来M行,每行表示一个操作
输出格式
若干行,一行一个整数,表示所求的第K小的数字
样例输入
5 5
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3
样例输出
0
7
提示
注意:如果有多个大小相同的数字,只把他们看做一个数字,如样例。
若找不到第K小的数,输出0
数据范围:
0<=N<=2,000,000
M<=1,000,000
-1,000,000,000<=每个整数<=1,000,000,000
思路:
范围太大,动态建立线段树:每次加入一个数,就将线段树对应叶节点的值改为1,若无该节点就建立;每次减少,对应叶节点改为0;每次查找,先查找左儿子是否有k个数,不足说明该找右儿子。
注意先判断是否存在左右儿子
#include<cstdio> #include<iostream> using namespace std; struct tree{int a,b,val;tree *le,*ri;}; tree NBHB,*temp; int k; bool mark=false; //................................................................... inline void in_(int &d) { bool mark=false;char t=getchar(); while(t<'0'||t>'9'){if(t=='-') mark=true;t=getchar();} for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)-'0'+t; if(mark)d=-d; } char o[100]; inline void out_(int x) { int l=1; if(x<0) x=-x,putchar('-'); if(!x) putchar('0'); for(;x;x/=10) o[l++]=x%10+'0'; for(l--;l;l--)putchar(o[l]); putchar('\n'); } //................................................................... void add(tree *t) { if(t->a==t->b) { t->val=1; return ; } int mid=t->a+t->b,x=t->a,y=t->b; mid=mid<0?mid/2-1:mid>>1; if(k<=mid) { if(t->le==NULL) { t->le=new tree; t->le->a=x,t->le->b=mid,t->le->le=t->le->ri=NULL; } add(t->le); } if(k>mid) { if(t->ri==NULL) { t->ri=new tree; t->ri->a=mid+1,t->ri->b=y,t->ri->le=t->ri->ri=NULL; } add(t->ri); } t->val=0; if(t->le!=NULL) t->val+=t->le->val; if(t->ri!=NULL) t->val+=t->ri->val; } void del(tree *t) { if(mark) return ; if(t->a==t->b) { t->val=0; return ; } int mid=t->a+t->b,x=t->a,y=t->b; mid=mid<0?mid/2-1:mid>>1; if(k<=mid) { if(t->le==NULL) { mark=true; return; } del(t->le); } if(k>mid) { if(t->ri==NULL) { mark=true; return; } del(t->ri); } t->val=0; if(t->le!=NULL) t->val+=t->le->val; if(t->ri!=NULL) t->val+=t->ri->val; } int find(tree *t,int k) { if(t->val<k) return 0; if((*t).a==(*t).b) return t->b; if(t->le!=NULL) { temp=t->le; if(temp->val>=k) return find(temp,k); else return find(t->ri,k-temp->val); } else return find(t->ri,k); } //................................................................... int main() { NBHB.a=-1000000000,NBHB.b=1000000000,NBHB.le=NULL,NBHB.ri=NULL; int n,m;in_(n),in_(m); for(int i=1;i<=n;i++) { in_(k); add(&NBHB); } for(int i=1,c;i<=m;i++) { in_(c),in_(k); if(c==1) add(&NBHB); else if(c==2) { mark=false; del(&NBHB); } else out_(find(&NBHB,k)); } }
相关文章推荐
- ARM9——中断学习
- 项目注意规范
- WPF编程宝典读书笔记——第10章 资源(一)
- socks5反向代理实现思路
- [0.0] 什么是机器学习
- setjmp和longjmp完成保存上下文和切换上下文的工作
- poj 2777 Count Color (线段树 区间更新 染色)
- 五、Zedboard学习之纯PL控制
- The Monocycle
- 基本知识点
- Java设计模式:工厂模式
- guava 常用API说明
- HTTP 和 SCOKET 通信的区别? TCP,UDP 的连接方法?HTTP 几种常用方式
- 分配内存的问题
- binlog
- sublime txt 设置在浏览器预览
- vijos1906:联合权值
- python核心编程第七章练习
- Dynamic Memory
- Java反射(二):反射的使用