zoukankan      html  css  js  c++  java
  • BZOJ2653 middle(二分答案+主席树)

      与中位数有关的题二分答案是很常用的trick。二分答案之后,将所有大于它的看成1小于它的看成-1,那么只需要判断是否存在满足要求的一段和不小于0。

      由于每个位置是1还是-1并不固定,似乎不是很好算。考虑暴力一点的想法:对于每一种答案预处理。这样查询就很好办了,线段树上每个区间维护最大前缀和后缀和及总和即可。并且可以发现按答案从小到大考虑的话每个位置都是开始一段为1之后为-1,总修改次数只有n次,建主席树即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 20010
    int n,m,a[N],b[N],root[N],lastans,cnt=0; 
    vector<int> p[N];
    struct data{int l,r,sum,pre,suf;
    }tree[N<<7];
    void build(int &k,int l,int r)
    {
        k=++cnt;tree[k].sum=tree[k].pre=tree[k].suf=r-l+1;
        if (l==r) return;
        int mid=l+r>>1;
        build(tree[k].l,l,mid);
        build(tree[k].r,mid+1,r);
    }
    void modify(int &k,int l,int r,int x)
    {
        tree[++cnt]=tree[k];k=cnt;
        tree[k].sum-=2;
        if (l==r) {tree[k].pre=tree[k].suf=-1;return;}
        int mid=l+r>>1;
        if (x<=mid)    modify(tree[k].l,l,mid,x);
        else modify(tree[k].r,mid+1,r,x);
        tree[k].pre=max(tree[tree[k].l].pre,tree[tree[k].l].sum+tree[tree[k].r].pre);
        tree[k].suf=max(tree[tree[k].r].suf,tree[tree[k].r].sum+tree[tree[k].l].suf);
    }
    int querysum(int k,int l,int r,int x,int y)
    {
        if (x>y) return 0;
        if (l==x&&r==y) return tree[k].sum;
        int mid=l+r>>1;
        if (y<=mid) return querysum(tree[k].l,l,mid,x,y);
        else if (x>mid) return querysum(tree[k].r,mid+1,r,x,y);
        else return querysum(tree[k].l,l,mid,x,mid)+querysum(tree[k].r,mid+1,r,mid+1,y);
    }
    int querypre(int k,int l,int r,int x,int y)
    {
        if (l==x&&r==y) return tree[k].pre;
        int mid=l+r>>1;
        if (y<=mid) return querypre(tree[k].l,l,mid,x,y);
        else if (x>mid) return querypre(tree[k].r,mid+1,r,x,y);
        else return max(querypre(tree[k].l,l,mid,x,mid),querysum(tree[k].l,l,mid,x,mid)+querypre(tree[k].r,mid+1,r,mid+1,y));
    }
    int querysuf(int k,int l,int r,int x,int y)
    {
        if (l==x&&r==y) return tree[k].suf;
        int mid=l+r>>1;
        if (y<=mid) return querysuf(tree[k].l,l,mid,x,y);
        else if (x>mid) return querysuf(tree[k].r,mid+1,r,x,y);
        else return max(querysuf(tree[k].r,mid+1,r,mid+1,y),querysum(tree[k].r,mid+1,r,mid+1,y)+querysuf(tree[k].l,l,mid,x,mid));
    }
    int calc(int k,int a,int b,int c,int d)
    {
        return querysum(root[k],1,n,b+1,c-1)+querysuf(root[k],1,n,a,b)+querypre(root[k],1,n,c,d);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2653.in","r",stdin);
        freopen("bzoj2653.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) b[i]=a[i]=read();
        sort(b+1,b+n+1);
        int t=unique(b+1,b+n+1)-b;
        for (int i=1;i<=n;i++)
        {
            a[i]=lower_bound(b+1,b+t,a[i])-b;
            p[a[i]].push_back(i);
        }
        build(root[1],1,n);
        for (int i=2;i<t;i++)
        {
            root[i]=root[i-1];
            for (int j=0;j<p[i-1].size();j++)
            modify(root[i],1,n,p[i-1][j]);
        }
        m=read();
        while (m--)
        {
            int q[4]={(read()+lastans)%n,(read()+lastans)%n,(read()+lastans)%n,(read()+lastans)%n};
            sort(q,q+4);
            int l=1,r=t-1,ans=0;
            while (l<=r)
            {
                int mid=l+r>>1;
                if (calc(mid,q[0]+1,q[1]+1,q[2]+1,q[3]+1)>=0) ans=mid,l=mid+1;
                else r=mid-1;
            }
            printf("%d
    ",lastans=b[ans]);
        }
        return 0;
    }
  • 相关阅读:
    Binary Tree Inorder Traversal
    Populating Next Right Pointers in Each Node
    Minimum Depth of Binary Tree
    Majority Element
    Excel Sheet Column Number
    Reverse Bits
    Happy Number
    House Robber
    Remove Linked List Elements
    Contains Duplicate
  • 原文地址:https://www.cnblogs.com/Gloid/p/9578010.html
Copyright © 2011-2022 走看看