• POJ


    题目大意:给你n个数,q个询问,每个询问问你在 l 到 r 之间的第k个数是多大。

    思路:很经典的一道题,有许多种做法。

    第一种:在挑战程序设计里面有介绍的分桶法。

    第二种:以建立一棵线段树,每个节点维护当前区间的有序数组。

    第三种:刚学的主席树,一棵普通的线段树在进行修改后是无法保存以前的线段树的,主席树的

    作用就是把线段树更新前后的版本都保留下来。对于l 到 r 第 k 大的, 我们只要比较r插入后的

    线段树版本和 l 插进来之前的线段树版本,就能找到第k大的数。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<vector>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=1e5+5;
     7 struct node
     8 {
     9     int l,r,sum;
    10 } seg[N*40];
    11 vector<int> v;
    12 int a[N],n,q,x,y,k,root[N],cnt;//root[i],表示插入第i数之后版本的树根。
    13 int get_id(int x){ return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}//二分查离散后的序号
    14 void update(int l,int r,int &x,int y,int pos)//注意x用引用,这样边进行递归,边给节点的父亲赋值。
    15 {
    16     seg[++cnt]=seg[y]; seg[cnt].sum++; x=cnt;
    17     if(l==r) return;
    18     int m=(l+r)>>1;
    19     if(m>=pos) update(l,m,seg[x].l,seg[y].l,pos);
    20     else update(m+1,r,seg[x].r,seg[y].r,pos);
    21 }
    22 int query(int l,int r,int x,int y,int k)
    23 {
    24     if(l==r) return l;
    25     int res=0,m=(l+r)>>1;
    26     res+=seg[seg[y].l].sum-seg[seg[x].l].sum;// 这是x和y 两个版本之间从l 到 m数量的差值。
    27     if(res>=k) return query(l,m,seg[x].l,seg[y].l,k); //如果差值大于等于k,说明第k个数在l 到 m之间
    28     else return query(m+1,r,seg[x].r,seg[y].r,k-res);
    29 }
    30 int main()
    31 {
    32     scanf("%d%d",&n,&q);
    33     for(int i=1;i<=n;i++) scanf("%d",&a[i]),v.push_back(a[i]);
    34     sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());//将数组里的数排序,去重进行离散化。
    35     for(int i=1;i<=n;i++) update(1,n,root[i],root[i-1],get_id(a[i]));
    36     for(int i=1;i<=q;i++)
    37     {
    38         scanf("%d%d%d",&x,&y,&k);
    39         printf("%d
    ",v[query(1,n,root[x-1],root[y],k)-1]);
    40     }
    41     return 0;
    42 }
    View Code

    还有一种整体二分的写法,整体二分是一种离线算法,对于只有一个询问的k小,我们可以二分答案,有m个询问,

    如果对每个都进行二分肯定会有冗余,整体二分就是进行一次二分答案,就能得出所有结果。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define fi first
      4 #define se second
      5 #define pb push_back
      6 #define mk make_pair
      7 #define pii pair<int,int>
      8 #define read(x) scanf("%d",&x)
      9 #define lread(x) scanf("%lld",&x)
     10 using namespace std;
     11 
     12 typedef long long ll;
     13 const int N=2e5+7;
     14 const int mod=1e9+7;
     15 const int base=17;
     16 const int inf=0x3f3f3f3f;
     17 const ll INF=0x3f3f3f3f3f3f3f3f;
     18 
     19 int n,m,tot,ans[N];
     20 pii a[N];
     21 struct Qus
     22 {
     23     int l,r,k,cnt,id;
     24 }qus[N],tmp[N];
     25 struct BIT
     26 {
     27     int a[N];
     28     void modify(int x,int v)
     29     {
     30         for(int i=x;i<=n;i+=i&-i)
     31             a[i]+=v;
     32     }
     33     int sum(int x)
     34     {
     35         int ans=0;
     36         for(int i=x;i;i-=i&-i)
     37             ans+=a[i];
     38         return ans;
     39     }
     40 }bit;
     41 void cal(int l,int r,int down,int mid)
     42 {
     43     int pos=lower_bound(a+1,a+1+n,mk(down,0))-a;
     44     for(int i=pos;i<=n && a[i].fi<=mid;i++)
     45         bit.modify(a[i].se,1);
     46     for(int i=l;i<=r;i++)
     47         qus[i].cnt=bit.sum(qus[i].r)-bit.sum(qus[i].l-1);
     48     for(int i=pos;i<=n && a[i].fi<=mid;i++)
     49         bit.modify(a[i].se,-1);
     50 
     51 }
     52 void work(int l,int r,int down,int up)
     53 {
     54     if(down>up || l>r) return;
     55     if(down==up)
     56     {
     57         for(int i=l;i<=r;i++)
     58             ans[qus[i].id]=down;
     59         return;
     60     }
     61     int mid=(up+down)>>1;
     62     int item1=l,item2=r;
     63     cal(l,r,down,mid);
     64     for(int i=l;i<=r;i++)
     65     {
     66         if(qus[i].cnt>=qus[i].k)
     67             tmp[item1++]=qus[i];
     68         else
     69         {
     70             qus[i].k-=qus[i].cnt;
     71             tmp[item2--]=qus[i];
     72         }
     73     }
     74     for(int i=l;i<=r;i++)
     75         qus[i]=tmp[i];
     76     work(l,item1-1,down,mid);
     77     work(item2+1,r,mid+1,up);
     78 }
     79 int main()
     80 {
     81     int mx=-inf,mn=inf;
     82     read(n); read(m);
     83     for(int i=1;i<=n;i++)
     84     {
     85         read(a[i].fi),a[i].se=i;
     86         mx=max(mx,a[i].fi);
     87         mn=min(mn,a[i].fi);
     88     }
     89     sort(a+1,a+n+1);
     90     for(int i=1;i<=m;i++)
     91     {
     92         read(qus[i].l);
     93         read(qus[i].r);
     94         read(qus[i].k);
     95         qus[i].id=i;
     96     }
     97     work(1,m,mn,mx);
     98     for(int i=1;i<=m;i++)
     99         printf("%d
    ",ans[i]);
    100     return 0;
    101 }
    102 /*
    103 */
    View Code
  • 相关阅读:
    Autofac的基本使用---4、使用Config配置
    Autofac的基本使用---3、泛型类型
    Autofac的基本使用---2、普通类型
    Autofac的基本使用---1、前言
    MVC中Autofac的使用
    EF快速入门--直接修改(简要介绍ObjectContext处理机制)
    EF生成模型时Disigner中无信息
    C语言关键字-volatile
    linux内核分析之内存管理
    (转)Linux SLUB 分配器详解
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7625850.html
Copyright © 2020-2023  润新知