zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    swift锁屏播放,音乐进度更新,专辑,歌手名显示
    swift Dictionary 字典
    Swift中的集合类型
    Swift String 一些常用方法
    Swift自定义Class实现Hashable
    二元最近的共同祖先问题(O(n) time 而且,只有一次遍历,O(1) Space (它不考虑函数调用栈空间))
    BZOJ1579 USACO 2009 Feb Gold 3.Revamping Trails Solution
    [DEEP LEARNING An MIT Press book in preparation]Linear algebra
    POJ--2391--Ombrophobic Bovines【分割点+Floyd+Dinic优化+二分法答案】最大网络流量
    c#-RTF文本编辑器
  • 原文地址:https://www.cnblogs.com/Kurokey/p/5621379.html
Copyright © 2011-2022 走看看