HDU 2852 KiKi's K-Number(动态过程求第K小数)
来源:互联网 发布:h3c路由器端口映射 sql 编辑:程序博客网 时间:2024/06/05 17:54
题意:
给出三种操作,
0 在容器中插入一个数。
1 在容器中删除一个数。
树状数组二分代码:(可见比线段树快了很多)
给出三种操作,
0 在容器中插入一个数。
1 在容器中删除一个数。
2 求出容器中大于a的第k大元素。
思路:可以用树状数组和线段树,显然a[1]+...+a[i]随i有明显的单调性,所以可以二分出答案
线段树时间复杂度比树状数组的常数大了几倍...所以线段树擦边过了
还有另外一种思路:二分只是二分出a[1]+...+a[i]的上界i,所以可以逆向考虑,从a[1]开始累加,直到到达k,这样的复杂度就由原来的
O(lgN*lgN) 变成O(lgN)了。难在累加的过程,线段树和树状数组是同样的累加方法详见代码
线段树二分代码:
129892102015-02-25 20:49:32Accepted28521965MS4176K2321 BC++ka
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int M = 100010;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1struct node{ int l,r; int sum;}tree[M<<2];int ans = 0;void build(int l,int r,int rt)//建树{ tree[rt].l =l; tree[rt].r =r; tree[rt].sum =0; if(l ==r ) return ; int m=(l+r)>>1; build(lson); build(rson);}void up(int rt){ tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;}void updata(int l,int r,int rt,int pos,int j){ if(l==r) { tree[rt].sum +=j; return; } int m=(tree[rt].l +tree[rt].r )/2; if(pos<=m) updata(lson,pos,j); else updata(rson,pos,j); up(rt);}int query(int rt,int L,int R){ int m=(tree[rt].l +tree[rt].r)>>1; if(L<=tree[rt].l&&tree[rt].r <=R) { return tree[rt].sum ; } int ans=0; if(L<=m) ans+=query(rt<<1,L,R); if(R>m) ans+=query(rt<<1|1,L,R); return ans;}int B_search(int k){ int lb = 1; int ub = M-1; int w=-1; while(lb<=ub) { int m = (lb + ub)>>1; ans=query(1,1,m); if(ans>=k) { ub = m - 1; w=m; } else { lb = m+1; } } return w;}int main(){ int n,a,b,k; while(~scanf("%d",&n)) { build(1,M,1); for(int i = 0;i<n;i++) { scanf("%d",&a); if(a==0) { scanf("%d",&b); updata(1,M,1,b,1); } else if(a==1) { scanf("%d",&b); ans=query(1,b,b); if(!ans) puts("No Elment!"); else updata(1,M,1,b,-1); } else if(a==2) { scanf("%d%d",&b,&k); ans=query(1,1,b); int tmp = B_search(ans+k); if(tmp==-1) puts("Not Find!"); else printf("%d\n",tmp); } } } return 0;}
树状数组二分代码:(可见比线段树快了很多)
//468MS 1484K#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>using namespace std;#define M 100100#define lowbit(x) (x&-x)int m;int C[M];void update(int rt,int val){ for(int i=rt;i<M;i+=lowbit(i)){ C[i]+=val; }}int sum(int rt){ int s=0; for(int i=rt;i>0;i-=lowbit(i)){ s+=C[i]; } return s;}int main(){ while(~scanf("%d",&m)){ int op; memset(C,0,sizeof(C)); while(m--){ scanf("%d",&op); if(op==0){ int x; scanf("%d",&x); update(x,1); } else if(op==1){ int x; scanf("%d",&x); if(sum(x)-sum(x-1)==0){ printf("No Elment!\n"); continue; } update(x,-1); } else { int x,k; scanf("%d%d",&x,&k); k+=sum(x); int lb=1,ub=M-1; while(ub>=lb){ int mid=(lb+ub)>>1; if(sum(mid)>=k) ub=mid-1; else lb=mid+1; } if(lb==M) printf("Not Find!\n"); else printf("%d\n",lb); } } } return 0;}
http://www.cnblogs.com/wuyiqi/archive/2011/12/25/2301071.html 这篇文章有解释
这样果然快了不少,跑到第11名
11ka312MS1484K1420B//312MS 1484K#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>using namespace std;#define M 100100#define lowbit(x) (x&-x)int m;int C[M];void update(int rt,int val){ for(int i=rt;i<M;i+=lowbit(i)){ C[i]+=val; }}int sum(int rt){ int s=0; for(int i=rt;i>0;i-=lowbit(i)){ s+=C[i]; } return s;}int find_kth(int k){ int ans=0,s=0; for(int i=20;i>=0;i--){ ans+=(1<<i); if(ans>=M||s+C[ans]>=k){ ans-=(1<<i); } else s+=C[ans]; } return ++ans;}int main(){ while(~scanf("%d",&m)){ int op; memset(C,0,sizeof(C)); while(m--){ scanf("%d",&op); if(op==0){ int x; scanf("%d",&x); update(x,1); } else if(op==1){ int x; scanf("%d",&x); if(sum(x)-sum(x-1)==0){ printf("No Elment!\n"); continue; } update(x,-1); } else { int x,k; scanf("%d%d",&x,&k); k+=sum(x); int ans=find_kth(k); if(ans==M) printf("Not Find!\n"); else printf("%d\n",ans); } } } return 0;}
//655MS 2660K#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;#define M 100100#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int tree[M<<2];bool flag;void up(int rt){ tree[rt]=tree[rt<<1]+tree[rt<<1|1];}bool update(int pos,int val,int l,int r,int rt){ flag=true; if(l==r){ if(val==-1&&tree[rt]==0){ flag=false; return false; } tree[rt]+=val; return true; } int m=(l+r)>>1; if(pos<=m) update(pos,val,lson); else update(pos,val,rson); up(rt); return flag? true:false;}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return tree[rt]; } int m=(l+r)>>1; int ans=0; if(L<=m) ans+=query(L,R,lson); if(R>m) ans+=query(L,R,rson); return ans;}void find_kth(int l,int r,int rt,int k){ if(l==r) { printf("%d\n",l); return ; } int m=(l+r)>>1; if(k<=tree[rt<<1]) find_kth(lson,k); else find_kth(rson,k-tree[rt<<1]);}int main(){ int m; while(~scanf("%d",&m)){ memset(tree,0,sizeof(tree)); while(m--){ int op; scanf("%d",&op); if(op==0){ int x; scanf("%d",&x); update(x,1,1,M-1,1); } else if(op==1){ int x; scanf("%d",&x); if(update(x,-1,1,M-1,1)==false) printf("No Elment!\n"); } else { int a,k; scanf("%d%d",&a,&k); k+=query(1,a,1,M-1,1); if(k>tree[1]){ printf("Not Find!\n"); continue; } find_kth(1,M-1,1,k); } } } return 0;}
0 0
- HDU 2852 KiKi's K-Number(动态过程求第K小数)
- HDU 2852——KiKi's K-Number(树状数组+二分查找, 第k大)
- HDU 2852 KiKi's K-Number
- hdu 2852 KiKi's K-Number
- hdu 2852 KiKi's K-Number
- hdu (2852) KiKi's K-Number
- HDU 2852 KiKi's K-Number
- hdu 2852 KiKi's K-Number
- hdu 2852 KiKi's K-Number
- hdu 2852 KiKi's K-Number(树状数组+二分)
- hdu 2852 KiKi's K-Number(线段树)
- HDU 2852 KiKi's K-Number(线段树+二分)
- hdu 2852 KiKi's K-Number(树状数组)
- HDU 2852 KiKi's K-Number(树状数组+二分)
- hdu 2852 KiKi's K-Number(树状数组)
- HDU 2852 KiKi's K-Number(单点更新,求值)
- HDU 2852 KiKi's K-Number(树状数组)
- HDU 2852 KiKi's K-Number(树状数组+二分)
- 5款替代微软Visio的开源免费软件
- SpringMVC中的XXE漏洞测试
- Feekood脚本语言概述
- 关于hibernate的缓存使用
- html+css实现图片转动
- HDU 2852 KiKi's K-Number(动态过程求第K小数)
- 蓝桥杯 地址转换 解题报告
- Binary String Matching
- 进程内存访问
- 反编译APK文件的方法
- JAVA-socket通信基础(2)
- firefox的缓存目录位置、清除、修改
- 05-面向对象编程
- netstat