P2824 [HEOI2016/TJOI2016]排序

【题意】给序列局部排序,问最终排序完成的q位置

【分析】考虑暴力,每次都sort修改局部排序部分,时间复杂度为O(nmlogn)

观察到题目只求q一个位置上的值,所以我们可以对这个答案进行二分,然后把序列根据比mid大/小来转换成0/1

对于0/1的排序,我们可以用线段树计算排序区间l,r的1的个数(也就是sum),如果排成升序然后把后面的改成1,前面的改成0即可

对于二分的每次judge都按照操作计算一遍,看q位是0还是1表示答案大了还是小了

【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=1e5+5;
int n,m,q,op[maxn],l[maxn],r[maxn];
int a[maxn],b[maxn];
struct segtree
{
    int l,r,sum,lz;
}tr[maxn<<2];
#define lson now<<1
#define rson now<<1|1
void fuzhi(int now,int val)
{
    tr[now].sum=(tr[now].r-tr[now].l+1)*val;
    tr[now].lz=val;
}
void pushdown(int now)
{
    if(tr[now].lz==-1) return;
    fuzhi(lson,tr[now].lz);
    fuzhi(rson,tr[now].lz);
    tr[now].lz=-1;
}
void pushup(int now)
{
    tr[now].sum=tr[lson].sum+tr[rson].sum;
}
void build(int now,int l,int r)
{
    tr[now].l=l; tr[now].r=r;
    if(l==r)
    {
        tr[now].sum=b[l];
        return;
    }
    int mid=l+r>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(now);
}
int query(int now,int l,int r)
{
    if(tr[now].l>=l && tr[now].r<=r)
    {
        return tr[now].sum;
    }
    int res=0;
    int mid=tr[now].l+tr[now].r>>1;
    pushdown(now);
    if(l<=mid) res+=query(lson,l,r);
    if(mid<r) res+=query(rson,l,r);
    return res;
}
void modify(int now,int l,int r,int val)
{
    if(tr[now].l>=l && tr[now].r<=r)
    {
        tr[now].sum=(tr[now].r-tr[now].l+1)*val;
        tr[now].lz=val;
        return;
    }
    int mid=tr[now].l+tr[now].r>>1;
    pushdown(now);
    if(l<=mid) modify(lson,l,r,val);
    if(mid<r) modify(rson,l,r,val);
    pushup(now);
}
bool check(int x)
{
    for(int i=1;i<=n*4;i++) tr[i].sum=0,tr[i].lz=-1;
    for(int i=1;i<=n;i++) b[i]=(a[i]>=x);
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int cntt=query(1,l[i],r[i]);
        if(!op[i])
        {
            modify(1,l[i],r[i]-cntt,0);
            modify(1,r[i]-cntt+1,r[i],1);
        }
        else
        {
            modify(1,l[i],l[i]+cntt-1,1);
            modify(1,l[i]+cntt,r[i],0);
        }
    }
    int cnt=query(1,q,q);
    return cnt;
}
int main()
{
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&op[i],&l[i],&r[i]);
    scanf("%d",&q);
    int L=1,R=n,ans=0;
    while(L<=R)
    {
        int mid=L+R>>1;
        if(check(mid)) L=mid+1,ans=mid;
        else R=mid-1;
    }
    printf("%d",ans);
    return 0;
}

 

posted @ 2021-05-10 22:49  andyc_03  阅读(36)  评论(0编辑  收藏  举报