"HEOI2016 / TJOI2016" ソート

トピックリンク

私は突きます

\(解決\)

この質問は、オフラインので、ここで彼らは実際の話を、オンラインの練習ではありません。

直接配列なので、その複雑さは明らかに間違っている。しかし、として記載されている番号ならば\(01 \)文字列は、その後、あなたは複雑に右折をすることができます

だから、\(01 \)文字列がどのようにそれを行うには?

私たちは、木のラインでこの事を維持することを検討してください。

私たちがしたいとし([L、R] \ \ ) ソート

我々が扱うことができる\([L、R]を\ ) に\(1 \)番号、我々は彼を聞かせて\(W \)

ASCはれる場合([R-X + 1 \ \、R])を1に設定され、バランスがある\(0 \)

降順にする場合\([L、L + X -1] \)はバランスがある、1に設定されている\(0 \)

そこで問題は、どのような状況になり?

私たちは、最終的な答えを二分法なので、この数がされ(MID \)\します

シーケンス番号よりも小さい\(MID \)のように、\(0 \) より大きい\(MID \)のように\(1 \)

ルートは、次に、上述したプロセスとして動作します。

最後の判決\(Q \)位置がある\(1 \)

、です\(L = MID。1 + \)

否、\(R =ミッド1 \)

今、何これは単調で証明します。

場合\(q個の\) この位置の数である(1 \)を\、次に答えが肯定的である\(X + 1、X + 2、X + 3 ... \) ので、右に間隔、およびその逆。

\(コード\)

#include<bits/stdc++.h>
#define rg register
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    return f*x;
}
struct node {
    int lazy,v;
}a[1000001];
int c[1000001];
void pushup(int k){
    a[k].v=a[k<<1].v+a[k<<1|1].v;
}
void build(int k,int l,int r){
    a[k].lazy=-1,a[k].v=0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
void pushdown(int k,int l,int r){
    if(a[k].lazy==-1) return;
    int mid=(l+r)>>1;
    a[k<<1].v=(mid-l+1)*a[k].lazy;
    a[k<<1|1].v=(r-mid)*a[k].lazy;
    a[k<<1].lazy=a[k<<1|1].lazy=a[k].lazy;
    a[k].lazy=-1;
}
void update(int k,int l,int r,int begin,int end,int v){
    if(r<begin||l>end) return ;
    if(r<=end&&l>=begin){
        a[k].v=(r-l+1)*v;
        a[k].lazy=v;
        return ;
    }
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    update(k<<1,l,mid,begin,end,v);
    update(k<<1|1,mid+1,r,begin,end,v);
    pushup(k);
}
int find(int k,int l,int r,int begin,int end){
    if(r<begin&&l>end) return 0;
    if(r<=end&&l>=begin) return a[k].v;
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    if(end<=mid)
        return find(k<<1,l,mid,begin,end);
    else if(begin>mid)
        return find(k<<1|1,mid+1,r,begin,end);
    else return find(k<<1,l,mid,begin,mid)+find(k<<1|1,mid+1,r,mid+1,end);
}
struct ans{
    int opt,x,y;
}b[1000001];
int n,m,ans,l,r,q;
bool check(int x){
    build(1,1,n);
    for(int i=1;i<=n;i++)
        update(1,1,n,i,i,c[i]>=x);
    for(int i=1;i<=m;i++){
        int opt=b[i].opt,x=b[i].x,y=b[i].y;
        int w1=find(1,1,n,x,y),w0=y-x+1-w1;
        if(opt==0)
            update(1,1,n,x,y,1),update(1,1,n,x,x+w0-1,0);
        else update(1,1,n,x,y,0),update(1,1,n,x,x+w1-1,1);
    }
    return find(1,1,n,q,q)==1;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) c[i]=read();
    for(int i=1;i<=m;i++) b[i].opt=read(),b[i].x=read(),b[i].y=read();
    l=1,r=n,q=read();
    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;
}

おすすめ

転載: www.cnblogs.com/hbxblog/p/11708862.html