poj2104(K-th Number)

题目链接:传送门

题目大意:给你一个数组,有m次询问,问区间x~y里面第k大的数是什么?

题目思路:            首先谨以此题纪念我即将挂掉的高数大物

     这个题是静态区间第K大数,因为后面没有加入新数,很多优秀的数据结构都能解决掉它,推荐一篇博客:传送门

     但是为了练习整体二分,于是参照网上博客(传送门),做成了整体二分。

     整体二分就是对答案和时间(动态时有效)的双重二分,理解起来稍有难度,理解之后感觉好神奇,再推荐一篇论文:传送门

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cstring>
  7 #include <stack>
  8 #include <cctype>
  9 #include <queue>
 10 #include <string>
 11 #include <vector>
 12 #include <set>
 13 #include <map>
 14 #include <climits>
 15 #define lson root<<1,l,mid
 16 #define rson root<<1|1,mid+1,r
 17 #define fi first
 18 #define se second
 19 #define ping(x,y) ((x-y)*(x-y))
 20 #define mst(x,y) memset(x,y,sizeof(x))
 21 #define mcp(x,y) memcpy(x,y,sizeof(y))
 22 using namespace std;
 23 #define gamma 0.5772156649015328606065120
 24 #define MOD 1000000007
 25 #define inf 0x3f3f3f3f
 26 #define N 106005
 27 #define maxn 5005
 28 typedef pair<int,int> PII;
 29 typedef long long LL;
 30 
 31 int n,m,k,num;
 32 int _min,_max;
 33 struct Node{
 34     int id,l,r,v,f;
 35     Node(){}
 36     Node(int a,int b,int c,int d,int e){
 37         id=a;l=b;r=c;v=d;f=e;
 38     }
 39 }node[N],t1[N],t2[N];
 40 int hcnt,ans[maxn];
 41 int tree[N];
 42 void add(int i,int v){
 43     for(;i<=n;i+=(i&(-i)))
 44         tree[i]+=v;
 45 }
 46 int query(int i){
 47     int res=0;
 48     for(;i;i-=(i&-i))
 49         res+=tree[i];
 50     return res;
 51 }
 52 void _solve(int ql,int qr,int l,int r){ ///ql,qr是操作的区间,l,r是答案的区间
 53     if(ql>qr)return;                    ///整体二分也是要对答案二分的
 54     if(l==r){        ///l==r说明答案已经确定,只要属于这个区间的询问都是这个答案
 55         for(int i=ql;i<=qr;++i)
 56             if(node[i].f==2)
 57                 ans[node[i].id]=l;
 58         return;
 59     }
 60     int mid=l+r>>1;
 61     int len1=0,len2=0;
 62     for(int i=ql;i<=qr;++i){
 63         if(node[i].f==1){
 64             if(node[i].v<=mid){   ///如果数比二分答案小,则它会对后半段操作有影响
 65                 add(node[i].id,1);
 66                 t1[len1++]=node[i];
 67             }
 68             else t2[len2++]=node[i];
 69         }
 70         else{
 71             int temp=query(node[i].r)-query(node[i].l-1);///前面有多少个数,决定之后的划分区间
 72             if(node[i].v>temp){ ///如果前面的数小于k个,说明答案在后半段
 73                 node[i].v-=temp;
 74                 t2[len2++]=node[i];
 75             }
 76             else t1[len1++]=node[i];///与上面同理
 77         }
 78     }
 79     for(int i=0;i<len1;++i)if(t1[i].f==1)add(t1[i].id,-1);///树状数组清空
 80     for(int i=0;i<len1;++i){node[ql+i]=t1[i];}
 81     for(int i=0;i<len2;++i){node[ql+len1+i]=t2[i];}
 82     _solve(ql,ql+len1-1,l,mid);
 83     _solve(ql+len1,qr,mid+1,r);
 84 }
 85 int main(){
 86     int i,j,group,x,y,v;
 87     while(scanf("%d%d",&n,&m)!=EOF){
 88         mst(tree,0);
 89         hcnt=0;_min=inf;_max=-inf;
 90         for(i=1;i<=n;++i){  ///这里我们是把初始给你的数组当作加入操作处理
 91             scanf("%d",&x);
 92             _min=min(_min,x);
 93             _max=max(_max,x);
 94             node[++hcnt]=Node(i,1,1,x,1);
 95         }
 96         for(i=1;i<=m;++i){
 97             scanf("%d%d%d",&x,&y,&v);
 98             node[++hcnt]=Node(i,x,y,v,2);
 99         }
100         _solve(1,hcnt,_min,_max);
101         for(int i=1;i<=m;++i)printf("%d
",ans[i]);
102     }
103     return 0;
104 }

还有离散化版本的

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <cstring>
  7 #include <stack>
  8 #include <cctype>
  9 #include <queue>
 10 #include <string>
 11 #include <vector>
 12 #include <set>
 13 #include <map>
 14 #include <climits>
 15 #define lson root<<1,l,mid
 16 #define rson root<<1|1,mid+1,r
 17 #define fi first
 18 #define se second
 19 #define ping(x,y) ((x-y)*(x-y))
 20 #define mst(x,y) memset(x,y,sizeof(x))
 21 #define mcp(x,y) memcpy(x,y,sizeof(y))
 22 using namespace std;
 23 #define gamma 0.5772156649015328606065120
 24 #define MOD 1000000007
 25 #define inf 0x3f3f3f3f
 26 #define N 106005
 27 #define maxn 5005
 28 typedef pair<int,int> PII;
 29 typedef long long LL;
 30 
 31 int a[N],b[N];
 32 int n,m,k,num;
 33 int _min,_max;
 34 struct Node{
 35     int id,l,r,v,f;
 36     Node(){}
 37     Node(int a,int b,int c,int d,int e){
 38         id=a;l=b;r=c;v=d;f=e;
 39     }
 40 }node[N],t1[N],t2[N];
 41 int hcnt,ans[maxn];
 42 int tree[N];
 43 void add(int i,int v){
 44     for(;i<=n;i+=(i&(-i)))
 45         tree[i]+=v;
 46 }
 47 int query(int i){
 48     int res=0;
 49     for(;i;i-=(i&-i))
 50         res+=tree[i];
 51     return res;
 52 }
 53 void _solve(int ql,int qr,int l,int r){ ///ql,qr是操作的区间,l,r是答案的区间
 54     if(ql>qr)return;                    ///整体二分也是要对答案二分的
 55     if(l==r){        ///l==r说明答案已经确定,只要属于这个区间的询问都是这个答案
 56         for(int i=ql;i<=qr;++i)
 57             if(node[i].f==2)
 58                 ans[node[i].id]=b[l];
 59         return;
 60     }
 61     int mid=l+r>>1;
 62     int len1=0,len2=0;
 63     for(int i=ql;i<=qr;++i){
 64         if(node[i].f==1){
 65             if(node[i].v<=mid){   ///如果数比二分答案小,则它会对后半段操作有影响
 66                 add(node[i].id,1);
 67                 t1[len1++]=node[i];
 68             }
 69             else t2[len2++]=node[i];
 70         }
 71         else{
 72             int temp=query(node[i].r)-query(node[i].l-1);///前面有多少个数,决定之后的划分区间
 73             if(node[i].v>temp){ ///如果前面的数小于k个,说明答案在后半段
 74                 node[i].v-=temp;
 75                 t2[len2++]=node[i];
 76             }
 77             else t1[len1++]=node[i];///与上面同理
 78         }
 79     }
 80     for(int i=0;i<len1;++i)if(t1[i].f==1)add(t1[i].id,-1);///树状数组清空
 81     for(int i=0;i<len1;++i){node[ql+i]=t1[i];}
 82     for(int i=0;i<len2;++i){node[ql+len1+i]=t2[i];}
 83     _solve(ql,ql+len1-1,l,mid);
 84     _solve(ql+len1,qr,mid+1,r);
 85 }
 86 int main(){
 87     int i,j,group,x,y,v;
 88     //freopen("in.txt","r",stdin);
 89     while(scanf("%d%d",&n,&m)!=EOF){
 90         mst(tree,0);
 91         hcnt=0;_min=1;_max=n;
 92         for(i=1;i<=n;++i){  ///这里我们是把初始给你的数组当作加入操作处理
 93             scanf("%d",&a[i]);
 94             b[i]=a[i];
 95         }
 96         sort(b+1,b+n+1);
 97         int len=unique(b+1,b+n+1)-b-1;
 98         for(i=1;i<=n;++i){
 99             int loc=lower_bound(b+1,b+len+1,a[i])-b;
100             node[++hcnt]=Node(i,1,1,loc,1);
101         }
102         for(i=1;i<=m;++i){
103             scanf("%d%d%d",&x,&y,&v);
104             node[++hcnt]=Node(i,x,y,v,2);
105         }
106         _solve(1,hcnt,_min,_max);
107         for(int i=1;i<=m;++i)printf("%d
",ans[i]);
108     }
109     return 0;
110 }
原文地址:https://www.cnblogs.com/Kurokey/p/5621379.html