[Luogu] P2824 sorting (two-point answer + line segment tree sorting)

  topic link

  Shock! The difference between two segment trees and one segment tree is 50 points!

  This question can be answered by two points, what is the last number in the position of the two points. How to verify it?

  Change the original sequence, all those greater than or equal to mid become 1, and all those less than mid become 0, and then the line segment tree is sorted.

  Finally, see whether the position is 1 or 0. If it is 1, it means that the last position is a number >=mid.

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define left (rt<<1)
#define right (rt<<1|1)
#define mid ((l+r)>>1)
#define lson l,mid,left
#define rson mid+1,r,right
#define maxn 300030
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num = num * 10 + ch - 0 ' ;
        ch=getchar();
    }
    return num*f;
}

struct Que{
    int opt,from,to;
}q[maxn];

int d[maxn],w[maxn];

int tree[maxn*4],mem[maxn*4],tag[maxn*4];
inline void pushup(int rt){    tree[rt]=tree[left]+tree[right];    }
inline void build(int l,int r,int rt){
    tree[rt]=mem[rt]=tag[rt]=0;
    if(l==r){
        tree[rt]=w[l];
        //printf("%d %d\n",l,w[l]);
        return;
    }
    build(lson);
    build(rson);
    pushup(rt);
}
inline void pushdown(int rt,int m){
    if(mem[rt]==0&&tag[rt]==0)    return;
    if(mem[rt]){
        mem[left]=mem[right]=1;
        tree[left]=tree[right]=0;
        tag[left]=tag[right]=0;
        mem[rt] = 0 ;
    }
    if(tag[rt]){
        tag[left]+=tag[rt];    tag[right]+=tag[rt];
        tree[left]+=m-(m>>1);
        tree[right]+=m>>1;
        tag[rt] = 0 ;
    }
    return;
}
void update(int from,int to,int l,int r,int rt){
    if(from<=l&&to>=r){
        tag[rt] ++ ;
        tree[rt]+=r-l+1;
        return;
    }
    pushdown(rt,r-l+1);
    if(from<=mid)    update(from,to,lson);
    if(to>mid)        update(from,to,rson);
    pushup(rt);
}
void memdate(int from,int to,int l,int r,int rt){
    if(from<=l&&to>=r){
        tag[rt]=0;    mem[rt]=1;
        tree[rt]=0;
        return;
    }
    pushdown(rt,r-l+1);
    if(from<=mid)    memdate(from,to,lson);
    if(to>mid)        memdate(from,to,rson);
    pushup(rt);
}
int query(int from,int to,int l,int r,int rt){
    if(from<=l&&to>=r)    return tree[rt];
    pushdown(rt,r-l+1);
    int ans=0;
    if(from<=mid)    ans+=query(from,to,lson);
    if(to>mid)        ans+=query(from,to,rson);
    return ans;
}


bool check(int lim,int n,int m,int last){
    build(1,n,1);
    for(int i=1;i<=m;++i){
        int opt=q[i].opt,from=q[i].from,to=q[i].to;
        int c1=query(from,to,1,n,1);
        int c2=to-from+1-c1;
        //printf("%d %d<<\n",c1,c2);
        memdate(from,to,1,n,1);
        if(opt==0)    update(from+c2,to,1,n,1);
        else    update(from,from+c1-1,1,n,1);
    }
    //printf("zero\n");
    //for(int i=1;i<=n;++i)    printf("%d ",zero.query(i,i,1,n,1));
    //printf("\none\n");
    //for(int i=1;i<=n;++i)    printf("%d ",one.query(i,i,1,n,1));
    //printf("\n");
    return query(last,last,1,n,1);
}

int main(){
    int n=read(),m=read();
    for(int i=1;i<=n;++i)    d[i]=read();
    for(int i=1;i<=m;++i)    q[i]=(Que){read(),read(),read()};
    int last=read();
    int l=1,r=n,ans=0;
    while(l<=r){
        //printf("%d %d %d\n",l,r,mid);
        for(int i=1;i<=n;++i)
            if(d[i]>=mid)    w[i]=1;
            else             w[i]=0;
        //for(int i=1;i<=n;++i)    printf("%d<",w[i]);
        //printf("\n");
        if(check(mid,n,m,last)){
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%d",ans);
    return 0;
}

 

Guess you like

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