• [国家集训队] middle


    一、题目

    点此看题

    二、解法

    我一开始的思路是枚举中位数,然后看它是否能成为中位数。如果我们把小于他的数看成 (-1) ,大于等于他的数看成 (1) ,那么当序列权值 (geq0) 的时候中位数是大于等于它的,暴力实现这个过程是 (O(n^2q)) 的。因为要枚举中位数,还要求 ([l_1,r_1)) 的最大后缀和 ((l_2,r_2]) 的最大前缀,两个各耗时 (O(n)) ,由于强制在线我们只能对他们都下手。

    枚举中位数怎么优化呢?细想一下满足单调性,那我们可以套一个二分嘛,恭喜你解决掉了一个 (O(n))

    但是这个求最大前缀 (/) 后缀就有一些麻烦了,因为每个数当中位数时所对应的各个位置的权值是不同的。有一个极其暴力的思路就是对每一个中位数都开一个数据结构(比如线段树),然后查询,但是难在预处理耗时太大。

    上述思路其实是可以延续的,考虑两个排序后相邻的数当中位数时他们两个的线段树是差不多的,差别可能就是某些位置由 (1) 变成了 (-1) ,那么我们可以用主席树来保存所有的线段树,因为每次修改的很少所以复杂度是对的,等于说我们用主席树完成了开 (n) 棵线段树的功能

    时间复杂度 (O(qlog^2n))

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int M = 20005;
    const int N = 50*M;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,q,cnt,ans,p[4],rt[M],b[M],ls[N],rs[N];
    struct node
    {
    	int x,id;
    	bool operator < (const node &b) const
    	{
    		return x<b.x;
    	}
    }a[M];
    struct data
    {
    	int l,r,sum;
    	data operator + (const data &b) const
    	{
    		return data{max(l,sum+b.l),max(b.r,b.sum+r),sum+b.sum};
    	}
    }tr[N],emp;
    void build(int &x,int l,int r)
    {
    	x=++cnt;
    	if(l==r)
    	{
    		tr[x].l=tr[x].r=tr[x].sum=1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(ls[x],l,mid);
    	build(rs[x],mid+1,r);
    	tr[x]=tr[ls[x]]+tr[rs[x]];
    }
    void ins(int &x,int y,int l,int r,int id,int f)
    {
    	x=++cnt;tr[x]=tr[y];
    	ls[x]=ls[y];rs[x]=rs[y];
    	if(l==r)
    	{
    		tr[x].l=tr[x].r=tr[x].sum=f;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(mid>=id) ins(ls[x],ls[y],l,mid,id,f);
    	else ins(rs[x],rs[y],mid+1,r,id,f);
    	tr[x]=tr[ls[x]]+tr[rs[x]];
    }
    data ask(int x,int l,int r,int L,int R)
    {
    	if(L>r || l>R) return emp;
    	if(L<=l && r<=R) return tr[x];
    	int mid=(l+r)>>1;
    	return ask(ls[x],l,mid,L,R)+ask(rs[x],mid+1,r,L,R); 
    }
    int check(int x)
    {
    	int res=ask(rt[x],1,n,p[0],p[1]-1).r;
    	res+=ask(rt[x],1,n,p[2]+1,p[3]).l;
    	res+=ask(rt[x],1,n,p[1],p[2]).sum;
    	return res>=0;
    }
    void dich(int l,int r)
    {
    	if(l>r) return ;
    	int mid=(l+r)>>1;
    	if(check(mid))
    	{
    		ans=mid;
    		dich(mid+1,r);
    	}
    	else dich(l,mid-1);
    }
    signed main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)
    		a[i]=node{read(),i};
    	sort(a+1,a+1+n);
    	build(rt[1],1,n);
    	int las=rt[1];
    	for(int i=1,j;i<=n;i=j)
    	{
    		j=i;m++;
    		for(;j<=n && a[j].x==a[i].x;j++)
    		{
    			b[m]=a[j].x;
    			ins(rt[m+1],las,1,n,a[j].id,-1);
    			las=rt[m+1];//以前写错了 
    		}
    	}
    	q=read();
    	while(q--)
    	{
    		for(int i=0;i<4;i++) p[i]=(read()+ans)%n+1;
    		sort(p,p+4);
    		dich(1,m);
    		printf("%d
    ",b[ans]);
    		ans=b[ans];//surprise mother fu**er 
    	}
    }
    
  • 相关阅读:
    mysql增加索引、删除索引、查看索引
    微信小程序跳转页面时参数过长导致参数丢失
    微信小程序:使用wx.request()请求后台接收不到参数
    微信小程序跳转web-vie时提示appId无法读取:Cannot read property 'appId' of undefined
    tomcat正常运行一段时间后,突然访问不了项目了
    注解@Async解决异步调用问题
    Linux之acl库的安装与使用(限制Linux某用户的访问权限)
    HashMap和Hashtable的详细区别
    如何处理MySQL经常出现CPU占用率达到99%
    IntelliJ IDEA 提交代码时出现:Code analysis failed with exception: com.intellij.psi......
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14237561.html
Copyright © 2020-2023  润新知