BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案

听说是BC原题。

好题,二分答案变成01序列,就可以方便的用线段树维护了。

然后就是区间查询和覆盖了。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define maxn 200005
 
int cnt[maxn<<2][2],data[maxn],n,m,a[maxn];
int opt[maxn],x[maxn],y[maxn],tag[maxn<<2],q;
 
void update(int o)
{
    F(i,0,1) cnt[o][i]=cnt[o<<1][i]+cnt[o<<1|1][i];
}
 
void build(int o,int l,int r)
{
    if (l==r)
    {
        cnt[o][data[l]]=1;
        cnt[o][1-data[l]]=0;
        tag[o]=-1;
        return ;
    }
    tag[o]=-1; int mid=l+r>>1;
    build(o<<1,l,mid); build(o<<1|1,mid+1,r);
    update(o);
}
 
void pushdown(int o,int l,int r)
{
    if (tag[o]!=-1)
    {
        int mid=l+r>>1;
        tag[o<<1]=tag[o<<1|1]=tag[o];
        cnt[o<<1][tag[o]]=mid-l+1;
        cnt[o<<1|1][tag[o]]=r-mid;
        cnt[o<<1][1-tag[o]]=0;
        cnt[o<<1|1][1-tag[o]]=0;
        tag[o]=-1;
    }
}
 
int query(int o,int l,int r,int L,int R)
{
    if (L<=l&&r<=R) return cnt[o][1];
    int mid=l+r>>1; pushdown(o,l,r);
    if (R<=mid) return query(o<<1,l,mid,L,R);
    else if (L>mid) return query(o<<1|1,mid+1,r,L,R);
    else return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
}
 
void modify(int o,int l,int r,int L,int R,int f)
{
    if (L>R) return ;
    if (L<=l&&r<=R)
    {
        tag[o]=f;
        cnt[o][f]=r-l+1;
        cnt[o][1-f]=0;
        return;
    }
    int mid=l+r>>1; pushdown(o,l,r);
    if (L<=mid) modify(o<<1,l,mid,L,R,f);
    if (R>mid)  modify(o<<1|1,mid+1,r,L,R,f);
    update(o);
}
 
void st_sort(int typ,int l,int r)
{
    int cnt1=query(1,1,n,l,r),cnt0=r-l+1-cnt1;
    if (typ==0)
    {
        modify(1,1,n,l,l+cnt0-1,0);
        modify(1,1,n,l+cnt0,r,1);
    }
    else
    {
        modify(1,1,n,l,l+cnt1-1,1);
        modify(1,1,n,l+cnt1,r,0); 
    }
}
 
bool check(int mid)
{
    F(i,1,n) data[i]=(a[i]>=mid); build(1,1,n);
    F(i,1,m)
    {
        st_sort(opt[i],x[i],y[i]);
    }
    if (query(1,1,n,q,q)) return true;
    else return false;
}
 
int main()
{
    scanf("%d%d",&n,&m);
    F(i,1,n) scanf("%d",&a[i]);
    F(i,1,m) scanf("%d%d%d",&opt[i],&x[i],&y[i]);
    int l=1,r=n;scanf("%d",&q);
    while(l<r)
    {
        int mid=(l+r)/2+1;
        if (check(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",l);
}

  

posted @ 2017-04-20 11:21  SfailSth  阅读(132)  评论(0编辑  收藏  举报