zoukankan      html  css  js  c++  java
  • BZOJ 2653 middle | 主席树

    题目:

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


    题解:

    设答案为ans,把大于等于ans的记为1,小于的记为-1,这样可以知道当前ans是大了还是小了

    然后二分答案,就是求最大子段和的问题,根据网上的题解:[b,c]是必选的,然后选[a,b]和[c,d]的最大字段和就行了

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 20010
    using namespace std;
    int sz,q,root[N],ls[N*20],rs[N*20],sum[N*20],lm[N*20],rm[N*20],n,m,b[5],lastans;
    struct node 
    {
        int p,v;
    }a[N];
    bool cmp(node a,node b)
    {
        return a.v<b.v;
    }
    void update(int k)
    {
        sum[k]=sum[ls[k]]+sum[rs[k]];
        lm[k]=max(lm[ls[k]],sum[ls[k]]+lm[rs[k]]);
        rm[k]=max(rm[rs[k]],sum[rs[k]]+rm[ls[k]]);
    }
    void build(int &rt,int l,int r)
    {
        rt=++sz;
        int mid=l+r>>1;
        if (l==r)
        {
            sum[rt]=lm[rt]=rm[rt]=1;
            return;
        }
        build(ls[rt],l,mid);
        build(rs[rt],mid+1,r);
        update(rt);
    }
    void insert(int x,int l,int r,int &y,int p,int v)
    {
        y=++sz;
        ls[y]=ls[x];
        rs[y]=rs[x];
        if (l==r)
        {
            sum[y]=lm[y]=rm[y]=v;
            return;
        }
        int mid=(l+r)>>1;
        if (p<=mid) insert(ls[x],l,mid,ls[y],p,v);
        else insert(rs[x],mid+1,r,rs[y],p,v);
        update(y);
    }
    int que1(int k,int l,int r,int ll,int rr)
    {
        if (ll==l&&r==rr) return sum[k];
        int mid=(l+r)>>1;
        if (rr<=mid) return que1(ls[k],l,mid,ll,rr);
        else if (ll>mid) return que1(rs[k],mid+1,r,ll,rr);
        else return que1(ls[k],l,mid,ll,mid)+que1(rs[k],mid+1,r,mid+1,rr);
    }
    int que2(int k,int l,int r,int ll,int rr)
    {
        if (ll==l&&r==rr) return rm[k];
        int mid=(l+r)>>1;
        if (rr<=mid) return que2(ls[k],l,mid,ll,rr);
        else if (ll>mid) return que2(rs[k],mid+1,r,ll,rr);
        else return max(que2(rs[k],mid+1,r,mid+1,rr),que1(rs[k],mid+1,r,mid+1,rr)+que2(ls[k],l,mid,ll,mid));
    }
    int que3(int k,int l,int r,int ll,int rr)
    {
        if (ll==l&&r==rr) return lm[k];
        int mid=(l+r)>>1;
        if (rr<=mid) return que3(ls[k],l,mid,ll,rr);
        else if (ll>mid) return que3(rs[k],mid+1,r,ll,rr);
        else return max(que3(ls[k],l,mid,ll,mid),que1(ls[k],l,mid,ll,mid)+que3(rs[k],mid+1,r,mid+1,rr));
    }
    bool judge(int k,int a,int b,int c,int d)
    {
        int temp(0);
        if (c-1>b) temp+=que1(root[k],0,n-1,b+1,c-1);
        temp+=que2(root[k],0,n-1,a,b);
        temp+=que3(root[k],0,n-1,c,d);
        return temp>=0;
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=0; i<n; i++)
        {
            scanf("%d",&a[i].v);
            a[i].p=i;
        }
        sort(a,a+n,cmp);
        build(root[0],0,n-1);
        for (int i=1; i<n; i++)insert(root[i-1],0,n-1,root[i],a[i-1].p,-1);
        scanf("%d",&q);
        for (int i=1; i<=q; i++)
        {
            scanf("%d%d%d%d",&b[0],&b[1],&b[2],&b[3]);
            for (int j=0; j<4; j++) b[j]=(b[j]+lastans)%n;
            sort(b,b+4);
            int l=0,r=n-1,x;
            while (l<=r)
            {
                int mid=(l+r)>>1;
                if (judge(mid,b[0],b[1],b[2],b[3])) x=mid,l=mid+1;
                else r=mid-1;
            }
            lastans=a[x].v;
            printf("%d
    ",lastans);
        }
    }
  • 相关阅读:
    django ---解决跨域的问题
    python-isinstance函数
    python每日一学-os模块常用函数
    调用父类方法super
    fiddler小运用-断点
    劝告
    Django model字段
    Jenkins自动化部署前端
    解决react使用antd table组件固定表头后,表头和表体列不对齐以及配置fixed固定左右侧后行高度不对齐
    高德地图判断点的位置是否在浏览器可视区域内
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8167795.html
Copyright © 2011-2022 走看看