【序列莫队+二分答案+树状数组】POJ2104-K-th Number

【题目大意】

给出一个长度为n的序列和m组查询(i,j,k),输出[i,j]中的第k大数。

【思路】

先离散化然后莫队分块。用树状数组来维护当前每个值的个数,然后对于每次询问二分答案即可。

又一次实力写错二分…(生无可恋脸.jpg)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const int MAXN=100000+50;
  8 const int MAXM=5000+50;
  9 struct node 
 10 {
 11     int l,r,k,pos,id,ans;
 12 }q[MAXM];
 13 bool cmp(node x,node y)
 14 {
 15     return (x.pos==y.pos)?x.r<y.r:x.pos<y.pos;
 16 }
 17 bool cmpid(node x,node y)
 18 {
 19     return (x.id<y.id);
 20 }
 21 struct discretize
 22 {
 23     int num,pos;
 24     bool operator < (const discretize &x) const {return (num<x.num);}
 25 }tmp[MAXN];
 26 int n,m;
 27 int a[MAXN],e[MAXN];
 28 int ori[MAXN];//离散化后的i对应的原数字为ori[i] 
 29 
 30 int lowbit(int x)
 31 {
 32     return (x&(-x));
 33 }
 34 
 35 void modify(int p,int x)
 36 {
 37     while (p<=n)
 38     {
 39         e[p]+=x;
 40         p+=lowbit(p);
 41     }
 42 }
 43 
 44 int sum(int p)
 45 {
 46     int ret=0;
 47     while (p>0)
 48     {
 49         ret+=e[p];
 50         p-=lowbit(p);
 51     }
 52     return ret;
 53 }
 54 
 55 void init()
 56 {
 57     scanf("%d%d",&n,&m);
 58     for (int i=1;i<=n;i++) 
 59     {
 60         scanf("%d",&tmp[i].num);
 61         tmp[i].pos=i;
 62     }
 63     sort(tmp+1,tmp+n+1);
 64     for (int i=1,j=0;i<=n;i++)
 65     {
 66         if (i==1 || tmp[i].num!=tmp[i-1].num) ++j,ori[j]=tmp[i].num;
 67         a[tmp[i].pos]=j;
 68     }
 69     int block=(int)sqrt(n);
 70     for (int i=1;i<=m;i++)
 71     {
 72         scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
 73         q[i].id=i;
 74         q[i].pos=(q[i].l-1)/block+1;
 75     }
 76     sort(q+1,q+m+1,cmp);
 77 }
 78 
 79 int binary_search(int k)
 80 {
 81     int lb=0,ub=n;
 82     while (ub-lb>1)
 83     {
 84         int mid=(ub+lb)>>1;
 85         if (sum(mid)>=k) ub=mid;else lb=mid;//注意一下二分怎么写 
 86     }
 87     return ub;
 88 } 
 89 
 90 void solve()
 91 {
 92     int l=1,r=0;
 93     memset(e,0,sizeof(e));
 94     for (int i=1;i<=m;i++)
 95     {
 96         while (l<q[i].l) modify(a[l],-1),l++;
 97         while (l>q[i].l) l--,modify(a[l],1);
 98         while (r<q[i].r) r++,modify(a[r],1);
 99         while (r>q[i].r) modify(a[r],-1),r--;
100         q[i].ans=binary_search(q[i].k);
101     }
102     sort(q,q+m+1,cmpid);
103     for (int i=1;i<=m;i++) printf("%d\n",ori[q[i].ans]);
104 }
105 
106 int main()
107 {
108     init();
109     solve();
110     return 0;    
111 } 

 

posted @ 2016-07-26 23:55  iiyiyi  阅读(233)  评论(0编辑  收藏  举报