zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    (十三)过滤器Filter(转)
    (十二)会话跟踪技术之servlet通信(forward和include)
    (十一)会话跟踪技术之作用域(request、session、servletContext)
    openjdk源码目录结构
    java socket相关的timeout
    eclipse创建maven web app
    hadoop mapred和mapreduce包
    hadoop shuffle
    bash shell和进程
    bash shell中的特殊用法
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366371.html
Copyright © 2011-2022 走看看