zoukankan      html  css  js  c++  java
  • bzoj 2653 middle(陈立杰) 二分枚举 + 可持久化线段树

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

    题目描述:
       给长度为20000的序列。求左端点在[a,b]和右端点在[c,d]中所有的子序列,最大的中位数。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 20005;
    struct info{
        int sum, mxl, mxr;
        info(){}
        info(int val){
            sum = mxl = mxr = val;
        }
    };
    info operator + (const info l, const info r){
        info mid ;
        mid .sum = l.sum + r.sum;
        mid .mxl = max(l.mxl , l.sum + max(r.mxl, 0 ));
        mid .mxr = max(r.mxr , r.sum + max(l.mxr, 0 ));
        return mid;
    }
    struct tree{
        int l,r;
        tree *pl, *pr;
        info v;
        tree (int _l, int _r, tree *_pl, tree *_pr)
        : l(_l), r(_r), pl (_pl), pr(_pr){
            v = pl->v + pr->v;
        }
        tree (int _l, int _r, int val): l(_l), r(_r){
            if(_l == _r) {
                v = info(val);
                return ;
            }
            int mid = l + r >>1;
            pl = new tree(l, mid, val);
            pr = new tree(mid+1, r, val);
            v = pl->v + pr->v;
        }
        info ask(int L,int R){
            if(L <= l && R >= r){
                return v;
            }
            int mid = l + r >> 1;
            if(mid < L) return pr->ask(L,R);
            else if(mid >= R) return pl->ask(L,R);
            else return pl ->ask(L,R) + pr ->ask(L,R);
        }
        tree* change(int pos, int val){
            if(l == r){
                return new tree(l,r,val);
            }
            int mid = l+r >>1;
            if(pos <= mid) return new tree(l,r,pl->change(pos,val),pr);
            return new tree(l,r,pl,pr->change(pos,val));
        }
        void OP(){
            cout<<l<<" "<<r<<" "<<v.mxl<<" "<<v.sum<<" "<<v.mxr<<endl;
            if(l==r) return;
            pl->OP();
            pr->OP();
        }
    };
    tree *root[N];
    pair<int,int> num[N];
    int a[N],n;
    bool chk(int m,int a,int b,int c,int d){
        tree *rt = root[m];
        int val =  rt->ask(a, b).mxr + (b+1<c ? rt->ask(b+1,c-1).sum : 0) + rt -> ask(c,d).mxl ;
        return val >= 0;
    }
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            num[i] = make_pair(a[i],i);
        }
        sort(num,num+n);
        root[0] = new tree(0,n-1,1);
        for(int i=1;i<n;i++){
            root[i] = root[i-1] -> change(num[i-1].second, -1);
        }
        int Q, last = 0;
        cin >>Q;
        while(Q--){
            int q[4];
            for(int i=0;i<4;i++){
                scanf("%d",&q[i]);
                q[i] = (q[i] + last) % n;
            }
            sort(q,q+4);
            int l = 0, r = n;
            while(l < r){
                int m = l+ r>>1;
                if(chk(m,q[0],q[1],q[2],q[3])) l = m+1;
                else r = m;
            }
            printf("%d
    ",num[l-1].first);
            last = num[l-1].first;
        }
        return 0;
    }
    

      

  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/tobec/p/3266411.html
Copyright © 2011-2022 走看看