bzoj 4552: [Tjoi2016&Heoi2016]排序

Posted wljss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4552: [Tjoi2016&Heoi2016]排序相关的知识,希望对你有一定的参考价值。

ODT&二分

看到没有人写关于ODT的题解,所以我决定来一发ODT题解。

首先这道题的的整体思路就是二分,关于二分的正确性可以感性的理解一下:我们每一次二分一个答案,然后将\(<mid\)的值变为1,\(\geq mid\)的变为0,每一次只用对0/1序列进行操作,倘若最后我们询问的位置上为0,说明这个位置上的值\(< mid\),否则就\(\geq mid\),所以它就具有可二分性。

让我们看看对0/1序列的操作,每次排序就相当于整体的0/1序列排序,也就是区间推平操作,所以我们就珂以用幸福的ODT来做这道题啦.我们每一次只用询问一下这个区间里一共有多少个1,然后将\(l\)\(l+len-1\)推平就好辣。当然这需要开O2(否则就死掉了),实测开了O2后跑的快的飞起。

最后献上我丑陋的代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<set>
#define IT set<node>::iterator
using namespace std;
int n,m,opt,k,ll,rr,ans;
int a[100010];
int l[100010],r[100010];
int pan[100010];

int read()

    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')if(ch=='-')w=-1;ch=getchar();
    while(ch>='0'&&ch<='9')s=s*10+ch-'0';ch=getchar();
    return s*w;




struct node

    int l,r;
    mutable int val;
    node(int L,int R=-1,int V=0):l(L),r(R),val(V)
    friend bool operator <(const node &a,const node &b)
    
        return a.l<b.l;
    
;

set<node>s;



IT split(int pos)

    IT it=s.lower_bound(node(pos));
    if(it!=s.end()&&it->l==pos)return it;
    --it;
    int L=it->l,R=it->r;
    int V=it->val;
    s.erase(it);
    s.insert(nodeL,pos-1,V);
    return s.insert(nodepos,R,V).first;


int sum(int l,int r)

    IT it2=split(r+1),it1=split(l);
    int res=0;
    for(;it1!=it2;++it1)
    if(it1->val)res+=(it1->r-it1->l+1);
    return res;



void tuiping(int l,int r,int v)

    IT it2=split(r+1),it1=split(l);
    s.erase(it1,it2);
    s.insert(nodel,r,v);


int check(int x)

    s.clear();
    int val=(a[1]>=x),len=1;
    for(int i=2;i<=n;++i)
    
        if((a[i]>=x)!=val)
        
            s.insert(nodei-len,i-1,val);
            val=(a[i]>=x);len=1;
        
        else len++;
    
    s.insert(noden-len+1,n,val);
    s.insert(noden+1,n+1,1);
    for(int i=1;i<=m;++i)
    
        if(pan[i]==0)//升序 
        
            int lin=r[i]-l[i]+1-sum(l[i],r[i]);//cout<<"lin="<<lin<<endl;
            tuiping(l[i],l[i]+lin-1,0);
            tuiping(l[i]+lin,r[i],1);
        
        else
        
            int lin=sum(l[i],r[i]);
            tuiping(l[i],l[i]+lin-1,1);
            tuiping(l[i]+lin,r[i],0);
        
    
    return sum(k,k);


void slove2()

    for(int i=1;i<=m;++i)pan[i]=(bool)read(),l[i]=read(),r[i]=read();
    cin>>k;
    int ans=0;
    ll=1;rr=n;//cout<<check(5)<<endl;;
    while(ll<=rr)
    
        int mid=(ll+rr)>>1;
        if(check(mid))
        
            ll=mid+1;
            ans=mid;
        
        else rr=mid-1;
    
    cout<<ans;




int main()

    //freopen("seq.in","r",stdin);
    //freopen("seq.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;++i)a[i]=read();
    slove2();
    fclose(stdin);fclose(stdout);
    return 0;

以上是关于bzoj 4552: [Tjoi2016&Heoi2016]排序的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4552][TJOI2016&&HEOI2016]排序

BZOJ4552:[Tjoi2016&Heoi2016]排序

[BZOJ] 4552: [Tjoi2016&Heoi2016]排序 #二分+线段树+算法设计策略

bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案

bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序

Bzoj4552: [Tjoi2016&Heoi2016]排序