zoukankan      html  css  js  c++  java
  • [国家集训队]middle

    [国家集训队]middle

    题目

    解法

    (n)颗线段树,将第(i)颗线段树中大于等于第(i)小的数权值赋为1,其他的则为-1,对于每个区间维护一个区间和,最大前缀和,最大后缀和。
    然后二分答案,查询二分到的答案对应线段树。
    (设s=[a,b-1]的最大后缀和+[b,c]的区间和+[c+1,d]的最大前缀和)
    (sgeq 0),则答案可能更大,否则答案必须变小,仔细想想为什么。
    这样不断二分即可。
    考虑到开不下那么多线段树,而若排序后相邻线段树维护的序列只有一个元素不同,所以我们考虑用主席树来维护。
    然后其实不需要离散化,离散化也没问题。

    完整代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    using namespace std;
    void ssort(int &a,int &b,int &c,int &d){
        if(a>b)swap(a,b);if(a>c)swap(a,c);if(a>d)swap(a,d);
        if(b>c)swap(b,c);if(b>d)swap(b,d);
        if(c>d)swap(c,d);
    }
    const int N=3e4;
    struct code{
        int x,id;
    }a[N];
    struct tree{
        int x,l,r,L,R,sum;
    }t[N*100],ans,fz;
    int cmp(code x,code y){return x.x<y.x;}
    int root[N],cnt,aa,bb,cc,dd,n;
    il void pushup(tree &no,tree l,tree r){
        no.L=max(l.L,l.sum+r.L);
        no.R=max(r.R,r.sum+l.R);
        no.sum=l.sum+r.sum;
    }
    int build(int l,int r){
        int no=++cnt;
        if(l==r){
            t[no].x=t[no].sum=t[no].L=t[no].R=1;
            return no;
        }
        int mid=l+r>>1;
        t[no].l=build(l,mid);
        t[no].r=build(mid+1,r);
        pushup(t[no],t[t[no].l],t[t[no].r]);
        return no;
    }
    int modify(int last,int l,int r,int k){
        int no=++cnt;
        if(l==r){
            t[no].x=t[no].sum=-1;
            return no;
        }
        t[no].l=t[last].l;
        t[no].r=t[last].r;
        int mid=l+r>>1;
        if(k<=mid)t[no].l=modify(t[last].l,l,mid,k);
        else t[no].r=modify(t[last].r,mid+1,r,k);
        pushup(t[no],t[t[no].l],t[t[no].r]);
        return no;
    }
    void query(int no,int l,int r,int L,int R){
        if(l>=L&&r<=R){
            pushup(ans,ans,t[no]);
            return ;
        }
        if(l>R||r<L||R<L)return ;
        int mid=l+r>>1;
        query(t[no].l,l,mid,L,R);
        query(t[no].r,mid+1,r,L,R);
    }
    int check(int x){
        int s=0;
        ans=fz;query(root[x],1,n,aa,bb-1);s+=ans.R;
        ans=fz;query(root[x],1,n,bb,cc);s+=ans.sum;
        ans=fz;query(root[x],1,n,cc+1,dd);s+=ans.L;
        return s>=0;
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i].x);
            a[i].id=i;
        }
        sort(a+1,a+n+1,cmp);
        root[0]=build(1,n);
        for(int i=1;i<=n;++i)
            root[i]=modify(root[i-1],1,n,a[i].id);
        int q,x=0;
        cin>>q;
        while(q--){
            scanf("%d%d%d%d",&aa,&bb,&cc,&dd);
            aa=(aa+x)%n+1;bb=(bb+x)%n+1;cc=(cc+x)%n+1;dd=(dd+x)%n+1;
            ssort(aa,bb,cc,dd);
            int l=0,r=n;
            while(l!=r){
                int mid=l+r>>1;
                if(check(mid+1))l=mid+1;
                else r=mid;
            }
            x=a[l+1].x;
            printf("%d
    ",x);
        }
    }
    
    
  • 相关阅读:
    cf1100 F. Ivan and Burgers
    cf 1033 D. Divisors
    LeetCode 17. 电话号码的字母组合
    LeetCode 491. 递增的子序列
    LeetCode 459.重复的子字符串
    LeetCode 504. 七进制数
    LeetCode 3.无重复字符的最长子串
    LeetCode 16.06. 最小差
    LeetCode 77. 组合
    LeetCode 611. 有效三角形个数
  • 原文地址:https://www.cnblogs.com/ljq-despair/p/8706936.html
Copyright © 2011-2022 走看看