hdu2852(2009多校第四场) 树状数组求区间第k大的数 两种方法

二分查找n*logn*logn

比较容易理解

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define maxx 100005
 5 using namespace std;
 6 int vis[100010],c[100010],k;
 7 int sum(int x)
 8 {
 9   int ret=0;
10   while (x>0){
11     ret+=c[x];
12     x-=(x&-x);
13   }
14   return ret;
15 }
16 void add(int x,int d)
17 {
18   while (x<=maxx){
19     c[x]+=d;
20     x+=(x&-x);
21   }
22 }
23 int binery(int l,int r)
24 {
25   int mid=l+(r-l)/2,t1,t2,t3;
26   t1=sum(l); t2=sum(mid); t3=sum(r);
27   if (t1==t3) return l;
28   if (t2<k) return binery(mid+1,r);
29   else return binery(l,mid);
30 }
31 int main()
32 {
33   int n,x,y;
34   while (~scanf("%d",&n))
35   {
36     memset(vis,0,sizeof(vis));
37     memset(c,0,sizeof(c));
38     while (n--)
39     {
40       scanf("%d",&x);
41       if (x==0)
42       {
43         scanf("%d",&y);
44         vis[y]++;
45         add(y,1);
46       }
47       else if (x==1)
48       {
49         scanf("%d",&y);
50         if (vis[y]==0){
51           printf("No Elment!\n");
52           continue;
53         }
54         vis[y]--;
55         add(y,-1);
56       }
57       else
58       {
59         scanf("%d%d",&y,&k);
60         if (sum(100000)-sum(y)<k){
61           printf("Not Find!\n");
62           continue;
63         }
64         k=sum(y)+k;
65         printf("%d\n",binery(1,100000));
66       }
67     }
68   }
69   return 0;
70 }
View Code

利用树状数组自身的特点,和数的二进制拆分关系

神奇优美的nlogn方法

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define maxx 100005
 5 using namespace std;
 6 int vis[100010],c[100010];
 7 int sum(int x)
 8 {
 9   int ret=0;
10   while (x>0){
11     ret+=c[x];
12     x-=(x&-x);
13   }
14   return ret;
15 }
16 void add(int x,int d)
17 {
18   while (x<=maxx){
19     c[x]+=d;
20     x+=(x&-x);
21   }
22 }
23 int find_kth(int k)
24 {
25   int ans=0,cnt=0,i;
26   for (i=20;i>=0;i--)
27   {
28     ans+=(1<<i);
29     if (ans>=maxx||cnt+c[ans]>=k)
30       ans-=(1<<i);
31     else cnt+=c[ans];
32   }
33   return ans+1;
34 }
35 int main()
36 {
37   int n,x,y,k;
38   while (~scanf("%d",&n))
39   {
40     memset(vis,0,sizeof(vis));
41     memset(c,0,sizeof(c));
42     while (n--)
43     {
44       scanf("%d",&x);
45       if (x==0)
46       {
47         scanf("%d",&y);
48         vis[y]++;
49         add(y,1);
50       }
51       else if (x==1)
52       {
53         scanf("%d",&y);
54         if (vis[y]==0){
55           printf("No Elment!\n");
56           continue;
57         }
58         vis[y]--;
59         add(y,-1);
60       }
61       else
62       {
63         scanf("%d%d",&y,&k);
64         if (sum(100000)-sum(y)<k){
65           printf("Not Find!\n");
66           continue;
67         }
68         printf("%d\n",find_kth(sum(y)+k));
69       }
70     }
71   }
72   return 0;
73 }
View Code

 

posted on 2014-12-15 22:20  xiao_xin  阅读(280)  评论(0编辑  收藏  举报

导航