• 【序列莫队+二分答案+树状数组】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
    ",ori[q[i].ans]);
    104 }
    105 
    106 int main()
    107 {
    108     init();
    109     solve();
    110     return 0;    
    111 } 
  • 相关阅读:
    347. 前 K 个高频元素(桶排序、堆排序)
    322. 零钱兑换 && 416. 分割等和子集(0-1背包问题)
    739. 每日温度 && 503. 下一个更大元素 II (单调栈)
    1110. 删点成林
    个人纪录
    pub get failed (server unavailable) -- attempting retry 1 in 1 second?
    python 遍历文件夹重命名
    flutter vscode 连接iphone失败
    部署以太坊合约
    Web漏洞扫描工具AppScan10介绍
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5709468.html
Copyright © 2020-2023  润新知