【HEOI2016/TJOI2016】排序(二份答案+线段树)

传送门

一道思路很好的题

首先考虑如果是0/1串该怎么做

我们发现我们可以在O(logn)O(log_n)的时间完成对这样一个序列的排序

queryquery出这个区间的和tottot

那么显然所有的11都到一边去了00到另一边去了

那么l(l+tot1)l-(l+tot-1)这个区间就都是00,剩下的都是1,那我们打一个区间覆盖标记就可以了

考虑到题目中给的是一个11~nn的全排列

所以我们可以直接二分这个位置是什么数

那么把整个序列中大于他的设为1,小于的设为0

那么就变成了上面说的0/1串问题

暴力O(mlogn)O(mlog_n)做一遍之后看qq这个位置上是0还是1

0就把上界调低,1就把下界调高

正确的就不用证明了吧

结果半天过不了发现二分和线段树宏冲突了
代码:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
#define lc (u<<1)
#define rc ((u<<1)+1)
#define mid ((l+r)>>1)
const int N=100005;
int op[N],L[N],k,R[N],val[N],tr[N<<2],mark[N<<2],n,m,a[N];
inline void pushup(int u){tr[u]=tr[lc]+tr[rc];}
inline void buildtree(int u,int l,int r){
    mark[u]=-1;
    if(l==r){tr[u]=a[l];return;}
    buildtree(lc,l,mid);
    buildtree(rc,mid+1,r);
    pushup(u);
}
inline void pushdown(int u,int p,int t){
    if(mark[u]==-1)return;
    mark[lc]=mark[rc]=mark[u];
    tr[lc]=mark[u]*p,tr[rc]=mark[u]*t;
    mark[u]=-1;
}
inline void update(int u,int l,int r,int st,int des,int k){
    if(des<l||r<st)return;
    if(l>=st&&r<=des){
        tr[u]=k*(r-l+1);
        mark[u]=k;return;
    }
    pushdown(u,mid-l+1,r-mid);
    update(lc,l,mid,st,des,k);
    update(rc,mid+1,r,st,des,k);
    pushup(u);
}
inline int query(int u,int l,int r,int st,int des){
    if(l>des||r<st)return 0;
    if(st<=l&&r<=des)return tr[u];
    pushdown(u,mid-l+1,r-mid);
    int ans=0;
    ans+=query(lc,l,mid,st,des);
    ans+=query(rc,mid+1,r,st,des);
    return ans;
}
inline bool check(int v){
    for(int i=1;i<=n;i++){
        if(val[i]>=v)a[i]=1;
        else a[i]=0;
    }
    buildtree(1,1,n);
    for(int i=1;i<=m;i++){
        int l=L[i],r=R[i];
        if(op[i]){
            int tmp=query(1,1,n,l,r);
            update(1,1,n,l,l+tmp-1,1);
            update(1,1,n,l+tmp,r,0);
        }
        else{
            int tmp=query(1,1,n,l,r);
            update(1,1,n,l,r-tmp,0);
            update(1,1,n,r-tmp+1,r,1);
        }
    }
    return query(1,1,n,k,k);
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)val[i]=read();
    for(int i=1;i<=m;i++)op[i]=read(),L[i]=read(),R[i]=read();
    k=read();
    int A=1,B=n,ans=0;
    while(A<=B){
        int py=(A+B)>>1;
        if(check(py))A=py+1,ans=py;
        else B=py-1;
    }
    cout<<ans;
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366371.html