zoukankan      html  css  js  c++  java
  • Optimal Subsequences(Hard Version)(二分套线段树+离线处理)

    题目链接:

    题解思路:首先按数组中的下标建一棵线段树,假设原数组是a,我们用一个新数组b记录a,将b数组先按权值排序、再按下标排序,然后再用数组记录m次询问,按k从小到大排序,再对每个询问二分线段树右边界,最后把m次询问按原来的顺序排回来,最后按顺序输出答案即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> PII;
    #define ls l,mid,rt<<1
    #define rs mid+1,r,rt<<1|1
    const int MAXN = 2e5+10;
    const double EPS = 1e-12;
    
    int T,n,m;
    int sum[MAXN<<2];
    struct A{
        int x,pos;
    }a[MAXN],b[MAXN];
    struct node{
        int k,pp,id,ans;
    }q[MAXN];
    
    inline void Update(int l,int r,int rt,int pos){
        if(pos==l&&l==r){
            sum[rt]=1;
            return ;
        }
        int mid=(l+r)/2;
        if(pos<=mid)Update(ls,pos);
        else Update(rs,pos);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    
    inline int Query(int l,int r,int rt,int pos){
        if(pos>=r)return sum[rt];
        int mid=(l+r)/2;
        int ans=0;
        ans+=Query(ls,pos);
        if(pos>mid)ans+=Query(rs,pos);
        return ans;
    }
    
    bool cmp1(A aa,A bb){
        if(aa.x!=bb.x)return aa.x>bb.x;
        else return aa.pos<bb.pos;
    }
    
    bool cmp2(node aa,node bb){
        return aa.k<bb.k;
    }
    
    bool cmp3(node aa,node bb){
        return aa.id<bb.id;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i].pos=i;
            b[i]=a[i];
        }
        sort(b+1,b+n+1,cmp1);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d %d",&q[i].k,&q[i].pp);
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp2);
        int now=1;
        for(int i=1;i<=m;i++){
            for(int j=now;j<=q[i].k;j++)Update(1,n,1,b[j].pos);
            now=q[i].k+1;
            int l=1,r=n,k;
            while(l<=r){
                int mid=(l+r)/2;
                if(Query(1,n,1,mid)<q[i].pp)l=mid+1;
                else {
                    r=mid-1;
                    k=mid;
                }
            }
            q[i].ans=a[k].x;
        }
        sort(q+1,q+m+1,cmp3);
        for(int i=1;i<=m;i++)printf("%d
    ",q[i].ans);
    }

    悄悄说一句,其实没必要二分,二分的log完全可以去掉...

    这里放一份去掉二分的代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int,int> PII;
    #define ls l,mid,rt<<1
    #define rs mid+1,r,rt<<1|1
    const int MAXN = 2e5+10;
    const double EPS = 1e-12;
    
    int T,n,m;
    int sum[MAXN<<2];
    struct A{
        int x,pos;
    }a[MAXN],b[MAXN];
    struct node{
        int k,pp,id,ans;
    }q[MAXN];
    
    inline void Update(int l,int r,int rt,int pos){
        if(pos==l&&l==r){
            sum[rt]=1;
            return ;
        }
        int mid=(l+r)/2;
        if(pos<=mid)Update(ls,pos);
        else Update(rs,pos);
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    
    inline int Query(int l,int r,int rt,int k){
        if(l==r)return a[l].x;
        int mid=(l+r)/2;
        if(sum[rt<<1]>=k)return Query(ls,k);
        else return Query(rs,k-sum[rt<<1]);
    }
    
    bool cmp1(A aa,A bb){
        if(aa.x!=bb.x)return aa.x>bb.x;
        else return aa.pos<bb.pos;
    }
    bool cmp2(node aa,node bb){ return aa.k<bb.k; }
    bool cmp3(node aa,node bb){ return aa.id<bb.id; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i].x); a[i].pos=i; b[i]=a[i]; } sort(b+1,b+n+1,cmp1); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d %d",&q[i].k,&q[i].pp); q[i].id=i; } sort(q+1,q+m+1,cmp2); int now=0; for(int i=1;i<=m;i++){ while(now<q[i].k)Update(1,n,1,b[++now].pos); q[i].ans=Query(1,n,1,q[i].pp); } sort(q+1,q+m+1,cmp3); for(int i=1;i<=m;i++)printf("%d ",q[i].ans); }
  • 相关阅读:
    CSU software 新手练习1 解题报告
    HDU 4067 Random Maze
    HDU 1853 Cyclic Tour
    Notepad++搭配MinGW编译运行C,C++程序
    ACM POJ3299-Humidex
    开始正常的做题了=。=
    写在杭电热身赛2之后
    大二了~
    Vim 学习笔记之cvim hot key
    The 10th Zhejiang Provincial Collegiate Programming Contest
  • 原文地址:https://www.cnblogs.com/Mmasker/p/11927495.html
Copyright © 2011-2022 走看看