[BZOJ4552] Sorting (TJOI & HEOI2016) - binary answer + line segment tree

Test address: Sorting
method: This question requires a binary answer + line segment tree.
When we saw some fancy operations on the sequence, we thought of using a line segment tree, but... this kind of operation seems to be impossible at all...
At this time, we found an important condition of this problem: the query is only once, and it is used in all After the modification operation. That said, we might be able to find a way to ask offline.
At this time we have to transform the problem. Considering the final sequence, we regard the entire sequence as being inserted into the corresponding positions one by one according to the numbers from large to small, then the number is the answer when the required position is put into the number for the first time. We found that it is monotonic whether there is a number in this position, that is, there is no number before a certain moment, and there is a number after that, so we consider the binary answer to find this moment, then it becomes a decision problem: How to judge what is going on m After sorting operations, is there a x number?
We divide all numbers into two categories, one is < x Yes, a class is x , we know that the number of the second category must be greater than the number of the first category, so we use 0 and 1 Representing these two types of numbers respectively, the problem is transformed into maintaining a 01 Sequence, which supports sorting operations. right 01 Sequence sorting can be divided into three steps: in the query interval 0 The number of , modify the number in a continuous segment to 0 , modify the numbers in another continuous segment to 1 . Obviously, these operations can be maintained with a segment tree. Then we solve this problem, the time complexity is O ( n log 2 n ) .
Here is my code:

#include <bits/stdc++.h>
using namespace std;
int n,m,q,x,a[100010],op[100010],L[100010],R[100010];
int seg[400010],p[400010];

void pushdown(int no,int l,int r)
{
    int mid=(l+r)>>1;
    if (p[no]!=-1)
    {
        p[no<<1]=p[no<<1|1]=p[no];
        if (!p[no])
        {
            seg[no<<1]=mid-l+1;
            seg[no<<1|1]=r-mid;
        }
        else seg[no<<1]=seg[no<<1|1]=0;
        p[no]=-1;
    }
}

void pushup(int no)
{
    seg[no]=seg[no<<1]+seg[no<<1|1];
}

void buildtree(int no,int l,int r)
{
    p[no]=-1;
    if (l==r)
    {
        if (a[l]>=x) seg[no]=0;
        else seg[no]=1;
        return;
    }
    int mid=(l+r)>>1;
    buildtree(no<<1,l,mid);
    buildtree(no<<1|1,mid+1,r);
    pushup(no);
}

void modify(int no,int l,int r,int s,int t,int type)
{
    if (s>t) return;
    if (l>=s&&r<=t)
    {
        p[no]=type;
        if (!type) seg[no]=r-l+1;
        else seg[no]=0;
        return;
    }
    int mid=(l+r)>>1;
    pushdown(no,l,r);
    if (s<=mid) modify(no<<1,l,mid,s,t,type);
    if (t>mid) modify(no<<1|1,mid+1,r,s,t,type);
    pushup(no);
}

int query(int no,int l,int r,int s,int t)
{
    if (l>=s&&r<=t) return seg[no];
    int mid=(l+r)>>1,sum=0;
    pushdown(no,l,r);
    if (s<=mid) sum+=query(no<<1,l,mid,s,t);
    if (t>mid) sum+=query(no<<1|1,mid+1,r,s,t);
    return sum;
}

bool check()
{
    buildtree(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int tot;
        tot=query(1,1,n,L[i],R[i]);
        if (!op[i])
        {
            modify(1,1,n,L[i],L[i]+tot-1,0);
            modify(1,1,n,L[i]+tot,R[i],1);
        }
        else
        {
            modify(1,1,n,R[i]-tot+1,R[i],0);
            modify(1,1,n,L[i],R[i]-tot,1);
        }
    }
    return !query(1,1,n,q,q);
}

int main()
{
    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;
    while(l<r)
    {
        x=((l+r)>>1)+1;
        if (check()) l=x;
        else r=x-1;
    }
    printf("%d",l);

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325163507&siteId=291194637