题意:
给出三种操作,
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)了。难在累加的过程,线段树和树状数组是同样的累加方法详见代码
线段树二分代码:
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;
}