HYSBZ 4552 成段更新

题意:

In 2016, Sister Jiayuan fell in love with the sequence of numbers. So he often studies some strange questions about sequences, and now he is studying a difficult problem
And need you to help him. The problem is this: Given a full permutation of 1 to n, now perform m local sorts on this full permutation sequence.
The order is divided into two types: 1: (0, l, r) means to sort the numbers of the interval [l, r] in ascending order 2: (1, l, r) means to sort the numbers of the interval [l, r] in descending order and finally ask Q
The number on the position.

The first line of input data is two integers n and m. n represents the length of the sequence, and m represents the number of partial sorts. 1 <= n, m <= 10 ^ 5 the second line is n integers
Number, representing a full permutation from 1 to n. Next enter m lines, each line has three integers op, l, r, op is 0 for ascending order, op is 1 for descending order
Sorting, l, r represents the sorted interval. Finally enter an integer q, where q is the position to ask after sorting, 1 <= q <= n. 1 <= n <= 10 ^ 5
, 1 <= m <= 10 ^ 5

The output data has only one line, an integer, which represents the number at the q position after all parts are sorted in order.


二分答案

假设现在要判断的是第 \(mid\) 位置的数

那么我们把数组中 \(\le a_{mid}\) 的数都标记成 0,\(>a_{mid}\) 的标记成 1,\(a\) 是数组

现在区间排序操作就简单了,数一下区间内有多少个 1 记为 \(s\)

如果是升序那就把区间右边 \(s\) 个位置区间赋值成 1,左边的区间赋值成 0

降序就把左边 \(s\) 个位置区间赋值成 1,右边的区间赋值成 0

最后操作完后判断一下第 \(mid\) 个数的标记

如果是 0 ,说明当前这个位置在操作完后的值 \(\le a_{mid}\) ,所以记录一下答案然后缩小右边界继续二分

如果是 1 ,说明当前这个位置在操作完后的值 \(>a_{mid}\),所以要缩小左边界

时间复杂度 \(O(n\log^2n)\)

// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
using namespace std;
const int MaxN=100050;
struct Quetion
{
    int opt,l,r;
}Q[MaxN];
template <class t> inline void read(t &s)
{
    s=0;
    reg int f=1;
    reg char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')
            f=-1;
        c=getchar();
    }
    while(isdigit(c))
        s=(s<<3)+(s<<1)+(c^48),c=getchar();
    s*=f;
    return;
}
// number of 1
int val[MaxN<<2],lazy[MaxN<<2];
int a[MaxN];
int n,m;
#define lson (u<<1)
#define rson (u<<1|1)
inline void pushup(int u)
{
    val[u]=val[lson]+val[rson];
    return;
}
inline void pushdown(int u,int l,int r)
{
    if(lazy[u]!=-1)
    {
        reg int mid=(l+r)>>1;
        lazy[lson]=lazy[u];
        lazy[rson]=lazy[u];
        val[lson]=lazy[u]*(mid-l+1);
        val[rson]=lazy[u]*(r-mid);
        lazy[u]=-1;
    }
    return;
}
inline void buildtr(int u,int l,int r,int std)
{
    if(l==r)
    {
        val[u]=(a[l]<=std?0:1);
        return;
    }
    reg int mid=(l+r)>>1;
    buildtr(lson,l,mid,std);
    buildtr(rson,mid+1,r,std);
    pushup(u);
    return;
}
inline void modify(int u,int l,int r,int ql,int qr,int k)
{
    if(ql>qr)
        return;
    if(ql<=l&&r<=qr)
    {
        lazy[u]=k;
        val[u]=k*(r-l+1);
        return;
    }
    pushdown(u,l,r);
    reg int mid=(l+r)>>1;
    if(ql<=mid)
        modify(lson,l,mid,ql,qr,k);
    if(mid<qr)
        modify(rson,mid+1,r,ql,qr,k);
    pushup(u);
    return;
}
/*
inline int query(int u,int l,int r,int kth)
{
    pushdown(u,l,r);
    if(l==r)
        return val[u];
    reg int mid=(l+r)>>1;
    if(kth<=val[lson])
        return query(lson,l,mid,kth);
    else
        return query(rson,mid+1,r,kth-val[lson]);
    return -1;
}
*/
inline int query(int u,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr)
        return val[u];
    pushdown(u,l,r);
    reg int mid=(l+r)>>1,ans=0;
    if(ql<=mid)
        ans+=query(lson,l,mid,ql,qr);
    if(mid<qr)
        ans+=query(rson,mid+1,r,ql,qr);
    return ans;
}
inline void print()
{
    puts("-=======-=-=-=-=-=-=-=");
    puts("segtree");
    for(int i=1;i<=n;++i)
        printf("%d ",query(1,1,n,i,i));
    puts("\n-======-=-=-=-=-=-\n");
}
inline void Init(int guess)
{
    memset(val,0,sizeof val);
    memset(lazy,-1,sizeof lazy);
    buildtr(1,1,n,guess);
    // puts("nyanpass~");
    // puts("in the beginning");
    // print();
    for(int i=1;i<=m;++i)
    {
        /*
        if(guess==25000&&i>=47110)
        {

        printf("Step #%d:\n",i);
        printf("[ %d , %d ]  option %d\n",Q[i].l,Q[i].r,Q[i].opt);
        }*/
        reg int mid=(Q[i].l+Q[i].r)>>1;
        if(!Q[i].opt)
        {

            reg int x=query(1,1,n,Q[i].l,Q[i].r);
            if(x>(Q[i].r-mid))
            {
/*
            if(guess==25000&&i>=47110)
            {
                puts("QAQ");
                printf("%d %d\n",Q[i].l,mid-(x-(Q[i].r-mid)));
            }
*/
            
                modify(1,1,n,mid+1,Q[i].r,1);
                
                modify(1,1,n,mid+1-(x-(Q[i].r-mid)),mid,1);
                
                modify(1,1,n,Q[i].l,mid-(x-(Q[i].r-mid)),0);
                // if(guess==25000&&i>=47110) puts("sss");
            }
            else if(x)
                modify(1,1,n,Q[i].r-x+1,Q[i].r,1),
                modify(1,1,n,Q[i].l,Q[i].r-x,0);
        }
        else
        {
            reg int x=query(1,1,n,Q[i].l,Q[i].r);
            if(x>(mid-Q[i].l+1))
            {
                modify(1,1,n,Q[i].l,mid,1);
                modify(1,1,n,mid+1,mid+x-(mid-Q[i].l+1),1);
                modify(1,1,n,mid+1+x-(mid-Q[i].l+1),Q[i].r,0);
            }
            else if(x)
                modify(1,1,n,Q[i].l,Q[i].l+x-1,1),
                modify(1,1,n,Q[i].l+x,Q[i].r,0);
        }
        // print();
    }
    return;
}
signed main(void)
{
    // freopen("D.in","r",stdin);
    // freopen("D-成段更新.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;++i)
        read(a[i]);
    for(int i=1;i<=m;++i)
    {
        read(Q[i].opt);read(Q[i].l);read(Q[i].r);
    }
    reg int q;cin>>q;
    reg int l=1,r=n,ans=-1,mid;
    /*
    for(int i=1;i<=n;++i)
    {
        printf("[[[[TEST]]]] %d\n",i);
        Init(i);
        print();
    }
    */
    while(l<=r)
    {
        mid=(l+r)>>1;
        // printf("lb: lr %d %d  mid %d\n",l,r,mid);
        Init(mid); // 0 <=    1 >
        // print();
        if(query(1,1,n,q,q))
            l=mid+1;
        else
            ans=mid,r=mid-1;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/chinesepikaync/p/12445208.html