标签:
题意:2 求出容器中大于a的第k大元素。
思路:可以用树状数组和线段树,显然a[1]+...+a[i]随i有明显的单调性,所以可以二分出答案
线段树时间复杂度比树状数组的常数大了几倍...所以线段树擦边过了
还有另外一种思路:二分只是二分出a[1]+...+a[i]的上界i,所以可以逆向考虑,从a[1]开始累加,直到到达k,这样的复杂度就由原来的
O(lgN*lgN) 变成O(lgN)了。难在累加的过程,线段树和树状数组是同样的累加方法详见代码
线段树二分代码:
12989210 | 2015-02-25 20:49:32 | Accepted | 2852 | 1965MS | 4176K | 2321 B | C++ | 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|1 struct 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名
11 | ka | 312MS | 1484K | 1420B |
//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|1 int 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; }
HDU 2852 KiKi's K-Number(动态过程求第K小数)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/43940589