• [POJ2104]K-th Number


    思路1:

    归并树+二分答案。

    首先构建一棵归并树,然后二分查找最小的数$x$使得被查找区间中小于等于$x$的数的个数大于等于$k$。

    注意vector中数字是从$0$开始存的,而询问是从$1$开始的,所以二分的时候要$-1$防止错位。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<vector>
     4 #define maxn 100000
     5 #define root 1
     6 #define _left <<1
     7 #define _right <<1|1
     8 using namespace std;
     9 int n,m,i,j,k;
    10 struct SegmentTree {
    11     vector<int> val[maxn<<2];
    12     void push_up(const int p,const int b,const int e) {
    13         val[p].resize(e-b+1);
    14         merge(val[p _left].begin(),val[p _left].end(),val[p _right].begin(),val[p _right].end(),val[p].begin());
    15     }
    16     void build(const int p,const int b,const int e) {
    17         if(b==e) {
    18             int t;
    19             cin>>t;
    20             val[p].push_back(t);
    21             return;
    22         }
    23         int mid=(b+e)>>1;
    24         build(p _left,b,mid);
    25         build(p _right,mid+1,e);
    26         push_up(p,b,e);
    27     }
    28     int query(const int p,const int b,const int e,const int l,const int r,const int x) {
    29         if((b==l)&&(e==r)) {
    30             return upper_bound(val[p].begin(),val[p].end(),x)-val[p].begin();
    31         }
    32         else {
    33             int mid=(b+e)>>1,ans=0;
    34             if(l<=mid) ans+=query(p _left,b,mid,l,min(mid,r),x);
    35             if(r>mid) ans+=query(p _right,mid+1,e,max(mid+1,l),r,x);
    36             return ans;
    37         }
    38     }
    39     void solve() {
    40         int b=1,e=n;
    41         while(b<e) {
    42             int mid=(b+e)>>1;
    43             if(query(root,1,n,i,j,val[root][mid-1])>=k) {
    44                 e=mid;
    45             }
    46             else {
    47                 b=mid+1;
    48             }
    49         }
    50         cout<<val[root][e-1]<<endl;
    51     }
    52 };
    53 SegmentTree tree;
    54 int main() {
    55     ios_base::sync_with_stdio(false);
    56     cin>>n>>m;
    57     tree.build(root,1,n);
    58     while(m--) {
    59         cin>>i>>j>>k;
    60         tree.solve();
    61     }
    62     return 0;
    63 }
    View Code

    思路2:

    主席树。
    建立一颗可持久化权值线段树,每次从$a$中取得一个数字时就将对应的数增加一个权值,并新增一条对应的链,那么每个节点上存储的数即位对应的数的权值前缀和。
    查询时只要每次判断左边的的权值和是否$≥k$,如果是,则说明要查询的数在左边,否则在右边,递归查询即可。

     1 #include<cstring>
     2 #include<utility>
     3 #include<iostream>
     4 #include<algorithm>
     5 const int N=100000,M=500001,SIZE=10000000;
     6 class FotileTree {
     7     private:
     8         int val[SIZE],sz,left[SIZE],right[SIZE];
     9         int newnode() {
    10             return sz++;
    11         }
    12     public:
    13         int root[M];
    14         FotileTree() {
    15             sz=0;
    16             memset(val,0,sizeof val);
    17         }
    18         int build(const int b,const int e) {
    19             int new_p=newnode();
    20             if(b==e) return new_p;
    21             int mid=(b+e)>>1;
    22             left[new_p]=build(b,mid);
    23             right[new_p]=build(mid+1,e);
    24             return new_p;
    25         }
    26         int modify(const int p,const int b,const int e,const int x) {
    27             int new_p=newnode();
    28             val[new_p]=val[p]+1;
    29             if(b==e) return new_p;
    30             int mid=(b+e)>>1;
    31             if(x<=mid) left[new_p]=modify(left[p],b,mid,x),right[new_p]=right[p];
    32             if(x>mid) right[new_p]=modify(right[p],mid+1,e,x),left[new_p]=left[p];
    33             return new_p;
    34         }
    35         int query(const int p1,const int p2,const int b,const int e,const int k) {
    36             if(b==e) return b;
    37             int mid=(b+e)>>1;
    38             if(val[left[p2]]-val[left[p1]]>=k) return query(left[p1],left[p2],b,mid,k);
    39             return query(right[p1],right[p2],mid+1,e,k-val[left[p2]]+val[left[p1]]);
    40         }
    41 };
    42 FotileTree t;
    43 int main() {
    44     std::ios_base::sync_with_stdio(false);
    45     std::cin.tie(NULL);
    46     int n,m;
    47     std::cin>>n>>m;
    48     t.root[0]=t.build(1,n);
    49     std::pair<int,int> a[n];
    50     int hash[n],antihash[n];
    51     for(int i=0;i<n;i++) {
    52         std::cin>>a[i].first;
    53         a[i].second=i;
    54     }
    55     std::sort(&a[0],&a[n]);
    56     for(int i=0;i<n;i++) {
    57         hash[a[i].second]=i+1;
    58         antihash[i]=a[i].first;
    59     }
    60     for(int i=1;i<=n;i++) t.root[i]=t.modify(t.root[i-1],1,n,hash[i-1]);
    61     while(m--) {
    62         int l,r,k;
    63         std::cin>>l>>r>>k;
    64         std::cout<<antihash[t.query(t.root[l-1],t.root[r],1,n,k)-1]<<std::endl;
    65     }
    66     return 0;
    67 }
    View Code

     思路3:

    树状数组+整体二分。
    同时对询问的区间和答案进行分治,属于同一区间的询问可以同时分治,
    用树状数组维护小于等于$mid$的数字个数$cnt$,
    如果$cntleq{k}$则往小二分,如果$cnt>k$则往大二分。
    以前也分别用归并树和主席树A过此题。
    注意每个数的值可能是负数,写读优时要注意。(每次做这题都因为这个原因WA过)

     1 #include<iostream>
     2 #include<algorithm>
     3 const int inf=0x7fffffff;
     4 const int N=200001,M=5001;
     5 struct Modify {
     6     int id,val;
     7     bool operator < (const Modify &x) const {
     8         return val<x.val;
     9     }
    10 };
    11 Modify a[N];
    12 struct Query {
    13     int a,b,k,cnt,id;
    14 };
    15 Query q[M],s[M];
    16 int n;
    17 class FenwickTree {
    18     private:
    19         int val[N];
    20         int lowbit(const int x) {
    21             return x&-x;
    22         }
    23     public:
    24         void modify(int p,const int x) {
    25             while(p<=n) {
    26                 val[p]+=x;
    27                 p+=lowbit(p);
    28             }
    29         }
    30         int query(int p) {
    31             int ans=0;
    32             while(p) {
    33                 ans+=val[p];
    34                 p-=lowbit(p);
    35             }
    36             return ans;
    37         }
    38 };
    39 FenwickTree t;
    40 int ans[M];
    41 void solve(int b,int e,int l,int r) {
    42     if(b==e) {
    43         for(int i=l;i<=r;i++) ans[q[i].id]=b;
    44         return;
    45     }
    46     int ll=1,rr=n+1;
    47     while(ll<rr) {
    48         int mid=(ll+rr)>>1;
    49         if(a[mid].val>=b) {
    50             rr=mid;
    51         }
    52         else {
    53             ll=mid+1;
    54         }
    55     }
    56     int mid=(b+e)>>1;
    57     for(int i=rr;i<=n&&a[i].val<=mid;i++) t.modify(a[i].id,1);
    58     for(int i=l;i<=r;i++) q[i].cnt=t.query(q[i].b)-t.query(q[i].a-1);
    59     for(int i=rr;i<=n&&a[i].val<=mid;i++) t.modify(a[i].id,-1);
    60     int tmpl=l,tmpr=r;
    61     for(int i=l;i<=r;i++) {
    62         if(q[i].cnt>=q[i].k) {
    63             s[tmpl++]=q[i];
    64         }
    65         else {
    66             q[i].k-=q[i].cnt;
    67             s[tmpr--]=q[i];
    68         }
    69     }
    70     for(int i=l;i<=r;i++) q[i]=s[i];
    71     if(tmpl!=l) solve(b,mid,l,tmpl-1);
    72     if(tmpr!=r) solve(mid+1,e,tmpr+1,r);
    73 }
    74 int main() {
    75     std::ios_base::sync_with_stdio(false);
    76     std::cin.tie(NULL);
    77     int m;
    78     std::cin>>n>>m;
    79     int min=inf,max=-inf;
    80     for(int i=1;i<=n;i++) {
    81         a[i].id=i;
    82         std::cin>>a[i].val;
    83         min=std::min(min,a[i].val);
    84         max=std::max(max,a[i].val);
    85     }
    86     std::sort(&a[1],&a[n+1]);
    87     for(int i=1;i<=m;i++) {
    88         std::cin>>q[i].a>>q[i].b>>q[i].k;
    89         q[i].id=i;
    90     }
    91     solve(min,max,1,m);
    92     for(int i=1;i<=m;i++) {
    93         std::cout<<ans[i]<<std::endl;
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    vue2.0对于数组变化不及时刷新视图的问题
    [Node]报错:gyp verb check python checking for Python executable "python2" in the PATH
    spring的@ControllerAdvice注解
    antdVue--Upload使用
    antd Vue--this.$confirm弹窗使用
    播放视频判断是否暂停_Javascript判断Video视频播放、暂停、结束完成及获取长度事件监听处理...
    P5400 [CTS2019]随机立方体
    P7502 「HMOI R1」不知道是啥的垃圾题
    vue3插槽使用
    cocos creator破解
  • 原文地址:https://www.cnblogs.com/skylee03/p/6847201.html
Copyright © 2020-2023  润新知