zoukankan      html  css  js  c++  java
  • BZOJ 2653 middle (可持久化线段树+中位数+线段树维护最大子序和)

    题意:

    左端点在[a,b],右端点在[c,d],求这个线段里中位数(上取整)最大值

    思路:

    对数组离散化,对每一个值建中位数的可持久化线段树(有重复也没事),就是对于root[i],大于等于i的值为1,小于的为-1,

    从小到大插入可持久化线段树即可

    如果中位数为m,那么从左端点到右端点[l,r]的序列和应该>=0,我们只需要二分这个m检查是不是序列和>=0即可

    满足左端点在[a,b],右端点在[c,d]的子序列和的最大值,就是我们在用线段树维护最大子序和时的

    [b+1,c-1]的sum+[a,b]的maxr+[c,d]的maxl

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    //#define lc root<<1
    //#define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e5+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int n;
    PI a[maxn];
    int q;
    vector<ll>v;
    int getid(ll x){
        return lower_bound(v.begin(), v.end(), x)-v.begin()+1;
    }
    bool cmp(PI a, PI b){
        if(a.fst==b.fst)return a.sc<b.sc;
        return a.fst<b.fst;
    }
    int root[maxn];
    struct Node{
        int maxl,maxr;
        int sum;
    }node[maxn*60];
    int ls[maxn],rs[maxn];
    int tot,totn;
    void build(int l, int r, int &root){
        root = ++tot;
        int mid = (l+r)>>1;
        if(l==r){
            node[root].maxl=node[root].maxr=node[root].sum=1;
            return;
        }
        build(l, mid, ls[root]);
        build(mid+1, r, rs[root]);
        node[root].maxl=max(node[ls[root]].sum+node[rs[root]].maxl, node[ls[root]].maxl);
        node[root].maxr=max(node[rs[root]].sum+node[ls[root]].maxr, node[rs[root]].maxr);
        node[root].sum=node[ls[root]].sum+node[rs[root]].sum;
        return;
    }
    void insert(int lst, int &now, int l, int r, int p){
        now = ++tot;
        ls[now]=ls[lst];
        rs[now]=rs[lst];
        node[now] = node[lst];
        int mid = (l+r)>>1;
        if(l==r){
            node[now].maxl=node[now].maxr=node[now].sum=-1;
            return;
        }
        if(p<=mid)insert(ls[lst], ls[now], l, mid, p);
        else insert(rs[lst], rs[now], mid+1, r, p);
        node[now].maxl=max(node[ls[now]].sum+node[rs[now]].maxl, node[ls[now]].maxl);
        node[now].maxr=max(node[rs[now]].sum+node[ls[now]].maxr, node[rs[now]].maxr);
        node[now].sum=node[ls[now]].sum+node[rs[now]].sum;
    }
    Node query(int ql, int qr, int l, int r, int now){
        
        int mid = (l+r)>>1;
        if(l==ql&&r==qr){
            return node[now];
        }
        else if(mid>=qr){
            return query(ql, qr, l, mid, ls[now]);
        }
        else if(mid<ql){
            return query(ql, qr, mid+1, r, rs[now]);
        }
        else{
            Node ans;
            Node lc=query(ql,mid,l,r,now);
            Node rc=query(mid+1,qr,l,r,now);
            ans.sum=lc.sum+rc.sum;
            ans.maxl=max(lc.sum+rc.maxl,lc.maxl);
            ans.maxr=max(rc.sum+lc.maxr,rc.maxr);
            return ans;
        }
    }
    void dfs(int x){
        printf("%d %d %d %d %d %d
    ",x,ls[x],rs[x],node[x].sum,node[x].maxl,node[x].maxr);
        if(ls[x])dfs(ls[x]);
        if(rs[x])dfs(rs[x]);
    }
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d" ,&a[i].fst);
            a[i].sc=i;
            v.pb(a[i].fst);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        totn=v.size();
        int lstans = 0;
        int tmp[5];
        sort(a+1,a+1+n,cmp);
        build(1,n,root[0]);
        for(int i = 1; i <= n; i++){
            insert(root[i-1],root[i],1,n,a[i].sc);
        }int q;
        //dfs(root[4]);
        scanf("%d", &q);
        while(q--){
            for(int i = 1; i <= 4; i++){
                scanf("%d", &tmp[i]);
                tmp[i]=(tmp[i]+lstans)%n;
            }
            sort(tmp+1,tmp+1+4);
            int l = 0;
            int r = n+1;
            int ans = 0;
            
            while(l<=r){
                int mid = (l+r)>>1;
                int res=max(query(tmp[1]+1,tmp[2]+1-1,1,n,root[mid-1]).maxr,0);
                res+=query(tmp[2]+1,tmp[3]+1,1,n,root[mid-1]).sum;
                res+=max(query(tmp[3]+1+1,tmp[4]+1,1,n,root[mid-1]).maxl,0);
                if(res>=0){
                    ans=mid;
                    l=mid+1;
                }
                else r = mid-1;
            }
            printf("%d
    ",lstans=v[ans-1]);
        }
        return 0;
    }
    /*
    5
    2 4 1 5 3
    3
    3 1 0 2
    2 3 1 4
    3 1 4 0
    
    5
    170337785
    271451044
    22430280
    969056313
    206452321
    3
    3 1 0 2
    2 3 1 4
    3 1 4 0
     */
  • 相关阅读:
    【转】 robotframework(rf)中对时间操作的datetime库常用关键字
    在RobotFramework--RIDE中把日期转化为整型进行运算
    Oracle中date转为timstam可以函数to_timestamp的方式来转化
    Java项目缺少.project文件
    数据库时间戳转换日期(MYSQL数据库)
    spring+struts+mybatis中关于报错org.hibernate.exception.GenericJDBCException: Connection is read-only. Queries leading to data modification are not allowed 的产生原因及解决方案
    新加字段问题(增加联合主键)
    集合问题
    数组面试题
    集合的问题
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10997394.html
Copyright © 2011-2022 走看看