zoukankan      html  css  js  c++  java
  • [BZOJ2653]middle

    bzoj
    luogu

    sol

    cls的题目,写起来挺容易但思维的确是挺神的。
    求中位数可以先二分中位数,然后把所有大于等于这个数的全部设为1,把所有小于这个数队全部设为-1,然后查一下区间总和是否大于等于0即可判断是否合法。
    但是显然不能对于每次询问这么搞一下,所以事先建立n棵主席树即可。
    查询的时候就是查[a,b]的最大后缀子段和,[b+1,c-1]的和,以及[c,d]的最大前缀子段和。判加起来是否大于等于0。

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 2e4+5;
    struct Data{
    	int vl,vr,sum;
    	Data operator + (const Data b) const
    		{
    			return (Data){max(vl,sum+b.vl),max(b.vr,b.sum+vr),sum+b.sum};
    		}
    };
    struct president_tree{int ls,rs;Data v;}t[N*50];
    int n,m,a[N],id[N],rt[N],tot,q[4],ans;
    bool cmp(int i,int j){return a[i]<a[j];}
    void build(int &x,int l,int r)
    {
    	x=++tot;
    	if (l==r) {t[x].v=(Data){1,1,1};return;}
    	int mid=l+r>>1;
    	build(t[x].ls,l,mid);build(t[x].rs,mid+1,r);
    	t[x].v=t[t[x].ls].v+t[t[x].rs].v;
    }
    void modify(int &x,int l,int r,int p)
    {
    	t[++tot]=t[x];x=tot;
    	if (l==r) {t[x].v=(Data){-1,-1,-1};return;}
    	int mid=l+r>>1;
    	if (p<=mid) modify(t[x].ls,l,mid,p);
    	else modify(t[x].rs,mid+1,r,p);
    	t[x].v=t[t[x].ls].v+t[t[x].rs].v;
    }
    Data query(int x,int l,int r,int ql,int qr)
    {
    	if (l>=ql&&r<=qr) return t[x].v;
    	int mid=l+r>>1;
    	if (qr<=mid) return query(t[x].ls,l,mid,ql,qr);
    	if (ql>mid) return query(t[x].rs,mid+1,r,ql,qr);
    	return query(t[x].ls,l,mid,ql,qr)+query(t[x].rs,mid+1,r,ql,qr);
    }
    int main()
    {
    	n=gi();
    	for (int i=1;i<=n;++i) a[i]=gi(),id[i]=i;
    	sort(id+1,id+n+1,cmp);
    	build(rt[1],1,n);
    	for (int i=2;i<=n;++i) modify(rt[i]=rt[i-1],1,n,id[i-1]);
    	m=gi();
    	while (m--)
    	{
    		for (int i=0;i<4;++i) q[i]=(gi()+ans)%n+1;
    		sort(q,q+4);
    		int l=1,r=n;
    		while (l<r)
    		{
    			int mid=l+r+1>>1,tmp=0;
    			tmp+=query(rt[mid],1,n,q[0],q[1]).vr;
    			tmp+=query(rt[mid],1,n,q[2],q[3]).vl;
    			if (q[1]+1<=q[2]-1) tmp+=query(rt[mid],1,n,q[1]+1,q[2]-1).sum;
    			if (tmp>=0) l=mid;
    			else r=mid-1;
    		}
    		printf("%d
    ",ans=a[id[l]]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    自学Java0711
    自学Java0710
    自学Java0709
    自学Java0708
    Leetcode刷题集
    网站收集
    674. 最长连续递增序列『简单』
    680. 验证回文字符串 Ⅱ『简单』
    686. 重复叠加字符串匹配『简单』
    693. 交替位二进制数『简单』
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8568974.html
Copyright © 2011-2022 走看看