• BZOJ2653: middle


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2653

    二分答案。对离散化后的每一个数都建立一棵区间线段树(然后可持久化掉),对于大于等于它的数设为1,否则设为-1 。

    然后对于询问只要找(a,b)之间的右起最大和+(c,d)之间的左起最大和+(b+1,c-1)之间的总和≥0就满足否则不满足。

    (注意一下如何维护左起最大和,右起最大和。。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 50050
    #define ll long long
    using namespace std;
    struct data{int id,x;
    }a[maxn];
    int sum[maxn*20],lsum[maxn*20],rsum[maxn*20],ls[maxn*20],rs[maxn*20];
    int root[maxn];
    int n,m,q[5],cnt,ans;
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    bool cmp(data a,data b){
        return a.x<b.x;
    }
    void up(int i){
        if (i==0) return;
        sum[i]=sum[ls[i]]+sum[rs[i]];
        lsum[i]=max(lsum[ls[i]],sum[ls[i]]+lsum[rs[i]]);
        rsum[i]=max(rsum[rs[i]],sum[rs[i]]+rsum[ls[i]]);
    }
    void build(int &i,int l,int r){
        i=++cnt;
        int mid=(l+r)/2;
        if (l==r){
            sum[i]=lsum[i]=rsum[i]=1; return;
        }
        build(ls[i],l,mid); build(rs[i],mid+1,r);
        up(i);
    }
    void add(int l,int r,int x,int &y,int val){
        y=++cnt;
        if (l==r) {sum[y]=lsum[y]=rsum[y]=-1; return;}
        int mid=(l+r)/2;
        ls[y]=ls[x]; rs[y]=rs[x];
        if (val<=mid) add(l,mid,ls[x],ls[y],val);
        else add(mid+1,r,rs[x],rs[y],val);
        up(y);
    }
    int qall(int i,int l,int r,int tl,int tr){
        if (tl==l&&r==tr) return sum[i];
        int mid=(l+r)/2;
        if (tr<=mid) return qall(ls[i],l,mid,tl,tr);
        else if (tl>mid) return qall(rs[i],mid+1,r,tl,tr);
        else return qall(ls[i],l,mid,tl,mid)+qall(rs[i],mid+1,r,mid+1,tr);
    }
    int ql(int i,int l,int r,int tl,int tr){
        if (tl==l&&r==tr) return lsum[i];
        int mid=(l+r)/2;
        if (tr<=mid) return ql(ls[i],l,mid,tl,tr);
        else if (tl>mid) return ql(rs[i],mid+1,r,tl,tr);
        else return max(ql(ls[i],l,mid,tl,mid),qall(ls[i],l,mid,tl,mid)+ql(rs[i],mid+1,r,mid+1,tr));
    } 
    int qr(int i,int l,int r,int tl,int tr){
        if (tl==l&&r==tr) return rsum[i];
        int mid=(l+r)/2;
        if (tr<=mid) return qr(ls[i],l,mid,tl,tr);
        else if (tl>mid) return qr(rs[i],mid+1,r,tl,tr);
        else return max(qall(rs[i],mid+1,r,mid+1,tr)+qr(ls[i],l,mid,tl,mid),qr(rs[i],mid+1,r,mid+1,tr));
    }
    bool jud(int a,int b,int c,int d,int x){
        int ans=0;
        ans=qr(root[x],0,n-1,a,b);
        ans+=ql(root[x],0,n-1,c,d);
        if (b+1<c) ans+=qall(root[x],0,n-1,b+1,c-1);
        if (ans>=0) return 1;
        return 0;  
    }
    int main(){
        n=read();
        rep(i,0,n-1) a[i].x=read(),a[i].id=i;
        sort(a,a+n,cmp);
        build(root[0],0,n-1);
        rep(i,1,n-1) add(0,n-1,root[i-1],root[i],a[i-1].id);
        m=read(); ans=0;
        rep(i,1,m){
            rep(j,1,4) q[j]=(read()+ans)%n; sort(q+1,q+1+4); 
            int rec=0;
            int l=0,r=n-1;
            while (l<=r){
                int mid=(l+r)/2;
                if (jud(q[1],q[2],q[3],q[4],mid)) {rec=mid; l=mid+1;}
                else r=mid-1;
            }
            ans=a[rec].x;
            printf("%d
    ",ans); 
            
        }
        return 0;
    }
  • 相关阅读:
    CF1438C Engineer Artem
    Python小程序:向SecureCRT发送命令
    PyInstaller,可将py脚本转换为exe
    在Virtual Box上安装linux系统,启动SSH服务
    Python介绍
    Git使用入门
    字符编码介绍
    适配器模式Adapter、外观模式Facade-- 学习HeadFirst设计模式记录
    复合模式Compound -- 学习HeadFirst设计模式记录
    代理模式Proxy-- 学习HeadFirst设计模式记录
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5066301.html
Copyright © 2020-2023  润新知