首页 > 其他分享 >【题解 P2839】 middle

【题解 P2839】 middle

时间:2023-11-24 13:23:42浏览次数:46  
标签:return P2839 题解 mid long middle leq num rc

[国家集训队] middle

题目描述

一个长度为 \(n\) 的序列 \(a\),设其排过序之后为 \(b\),其中位数定义为 \(b_{n/2}\),其中 \(a,b\) 从 \(0\) 开始标号,除法下取整。

给你一个长度为 \(n\) 的序列 \(s\)。

回答 \(Q\) 个这样的询问:\(s\) 的左端点在 \([a,b]\) 之间,右端点在 \([c,d]\) 之间的子区间中,最大的中位数。

其中 \(a<b<c<d\)。

位置也从 \(0\) 开始标号。

我会使用一些方式强制你在线。

输入格式

第一行序列长度 \(n\)。

接下来 \(n\) 行按顺序给出 \(a\) 中的数。

接下来一行 \(Q\)。

然后 \(Q\) 行每行 \(a,b,c,d\),我们令上个询问的答案是 \(x\)(如果这是第一个询问则 \(x=0\))。

令数组 \(q=\{(a+x)\bmod n,(b+x)\bmod n,(c+x)\bmod n,(d+x)\bmod n\}\)。

将 \(q\) 从小到大排序之后,令真正的要询问的 \(a=q_0\),\(b=q_1\),\(c=q_2\),\(d=q_3\)。

输入保证满足条件。

输出格式

\(Q\) 行依次给出询问的答案。

样例 #1

样例输入 #1

5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0

样例输出 #1

271451044
271451044
969056313

提示

对于 \(5\%\) 的数据,\(n,Q \leq 100\);

对于另 \(25\%\) 的数据,\(n \leq 2000\);

对于 \(100\%\) 的数据,\(1\leq n \leq 20000\),\(1\leq Q \leq 25000\),\(1\leq a_i\leq 10 ^ 9\)。

解题思路

首先,看到中位数,我们可以考虑二分,将小于 \(mid\) 的值设为 \(-1\) ,将大于 \(mid\) 的值设为 \(1\) ,这样根据题中的定义,若一段区间的和大于等于 \(0\) ,说明这段区间的中位数是大于等于 \(mid\) 的。
但同时,它的区间的左右端点是不固定的,在 \(a,b\) 中选左端点,在 \(c,d\) 中选右端点,这样的话 \([b+1,c-1]\) 这部分是固定的,我们就需要解决一个类似找区间前缀和或后缀和最大的问题。
容易发现,这个可以用线段树解决。
我们可以据此 \(O(mnlog^2n)\) 的解决问题,连 \(mnlogn\) 都不如。
每次都重建线段树都太麻烦了,我们可以发现,离散化原序列后,它每次建的线段树最多就 \(n\) 中,这样的话,我们可以将这样的 \(n\) 种线段树处理出来,时间复杂度 \(O(n^2logn+mlog^2n)\) ,但空间复杂度到了 \(n^2\)。
从小到大的修改,它最多只会修改 \(n\) 次,每个数最多只修改 \(1\) 次,那我们可以尝试用可持久化线段树来解决了。
时间复杂度 \(O(nlogn+mlog^2n)\) 。

Code

#include<bits/stdc++.h>
using namespace std;
struct data
{
	long long x,y;
}b[200005];
struct datay
{
	long long v,lc,rc,ls,rs;
}a[1000005];
long long n,d[20005],root[20005],m,op[6],num,dd[20005];
set<long long> l;
map<long long,long long> p;
void up(long long x)
{
	a[x].v=a[a[x].lc].v+a[a[x].rc].v;
	a[x].ls=max(a[a[x].lc].ls,a[a[x].lc].v+a[a[x].rc].ls);
	a[x].rs=max(a[a[x].rc].rs,a[a[x].rc].v+a[a[x].lc].rs);
	return;
}
bool cmp(data q,data w)
{
	return q.x<w.x;
}
long long build(long long l,long long r)
{
	if(l==r)
	{
		a[++num].v=1;
		a[num].ls=a[num].rs=1;
		return num;
	}
	long long mid=(l+r)>>1,p=++num;
	a[p].lc=build(l,mid);
	a[p].rc=build(mid+1,r);
	up(p);
	return p;
}
long long dijah(long long x,long long l,long long r,long long k,long long v)
{
	if(l==r)
	{
		a[++num].v=v;
		a[num].ls=a[num].rs=v;
		return num;
	}
	long long mid=(l+r)>>1,p=++num;
	a[p]=a[x];
	if(k<=mid)a[p].lc=dijah(a[x].lc,l,mid,k,v);
	else a[p].rc=dijah(a[x].rc,mid+1,r,k,v);
	up(p);
	return p;
}
long long gaia_v(long long x,long long ql,long long qr,long long l,long long r)
{
	if(l>r)return 0;
	if(ql<=l&&r<=qr)return a[x].v;
	long long mid=(l+r)>>1,h=0;
	if(ql<=mid)h+=gaia_v(a[x].lc,ql,qr,l,mid);
	if(qr>mid)h+=gaia_v(a[x].rc,ql,qr,mid+1,r);
	return h;
}
datay gaia_s(long long x,long long ql,long long qr,long long l,long long r)
{
	if(ql<=l&&r<=qr)return a[x];
	long long mid=(l+r)>>1;
	if(qr<=mid)return gaia_s(a[x].lc,ql,qr,l,mid);
	if(mid<ql)return gaia_s(a[x].rc,ql,qr,mid+1,r);
	datay q=gaia_s(a[x].lc,ql,qr,l,mid),w=gaia_s(a[x].rc,ql,qr,mid+1,r);
	datay e;
	e.v=q.v+w.v;
	e.ls=max(q.ls,q.v+w.ls);
	e.rs=max(w.rs,w.v+q.rs);
	return e;
}
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&b[i].x);
		l.insert(b[i].x);
	}
	long long g=0,xx,xy,yx,yy,ll,rr,mid;
	set<long long>::iterator q=l.begin();
	for(;q!=l.end();q++)
	{
		p[*q]=++g;
		d[g]=*q;
	}
	for(int i=1;i<=n;i++)b[i].x=p[b[i].x],b[i].y=i;
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++)dd[i]=d[b[i].x];
	root[0]=build(1,n);
	for(int i=1;i<=n;i++)
	{
		root[i]=dijah(root[i-1],1,n,b[i].y,-1);
	}
	long long s=0;
	scanf("%lld",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld%lld",&xx,&xy,&yx,&yy);
		op[1]=xx+s;
		op[2]=xy+s;
		op[3]=yx+s;
		op[4]=yy+s;
		op[1]%=n,op[2]%=n,op[3]%=n,op[4]%=n;
		sort(op+1,op+5);
		op[1]++,op[2]++,op[3]++,op[4]++;
		s=0;
		xx=op[1],xy=op[2],yx=op[3],yy=op[4];
		ll=1,rr=n;
		while(ll<=rr)
		{
			mid=(ll+rr)/2;
			if(gaia_s(root[mid-1],xx,xy,1,n).rs+gaia_v(root[mid-1],xy+1,yx-1,1,n)+gaia_s(root[mid-1],yx,yy,1,n).ls>=0)ll=mid+1,s=max(s,mid);
			else rr=mid-1;	
		}
		s=dd[s];
		printf("%lld\n",s);
	}








  return 0;
}

标签:return,P2839,题解,mid,long,middle,leq,num,rc
From: https://www.cnblogs.com/dijah/p/17853518.html

相关文章

  • CF1864D 题解
    我们注意到对如图倒三角形上的所有点操作都会影响到目标点。那么我们可以维护两个前缀和,第一个前缀和表示如下的点是否操作第二个前缀和表示这些点是否操作这样我们求出了前缀和之后,将两个前缀和异或一下就知道该点是否要操作了。#include<bits/stdc++.h>usingnamespace......
  • apache ftpserver服务器安装及服务启动问题解决
     在安装apacheftpserver后作为系统服务启动时遇到不能启动成功的问题,在网上各种搜索,发现很多人也遇到了同样的问题,折腾了1天,尝试了添加dll动态链接库、tomcat.exe替换ftpd.exe等还是没搞定。最后查看服务安装脚本service.bat,发现问题所在,现记录下过程中遇到的坑,分享出来参考,避......
  • Vue + Element UI 实现复制当前行数据功能(复制到新增页面组件值不能更新等问题解决)
    1、需求使用Vue+ElementUI实现在列表的操作栏新增一个复制按钮,复制当前行的数据可以打开新增弹窗后亦可以跳转到新增页面,本文实现为跳转到新增页面。2、实现1)列表页index.vue<el-table><!--其他列--><el-table-columnlabel="操作"width="150"><templateslot-s......
  • Vue + Element UI 实现复制当前行数据功能(复制到新增页面组件值不能更新等问题解决)
    1、需求使用Vue+ElementUI实现在列表的操作栏新增一个复制按钮,复制当前行的数据可以打开新增弹窗后亦可以跳转到新增页面,本文实现为跳转到新增页面。2、实现1)列表页index.vue<el-table><!--其他列--><el-table-columnlabel="操作"width="150"><templateslot-scope=......
  • centos7下开机磁盘报错不能进去liunx系统问题解决
    报错如下: centos7开机可以看到xfs(dm-0)磁盘报错,只有centos7自带修复磁盘,命令进行修复。xfs_repair-v-L/dev/dm-0然后等待输出done字样,代表修复完成。如果执行上条命令报错,可以先卸载找执行修复。 umount-l/dev/sda2然后执行修复,之后重启服务器。然后输入reboo......
  • 电脑网站支付报错“验签出错,建议检查签名字符串或私钥与应用公钥是否匹配”问题解决记
    在对接支付宝电脑网站支付的时候,遇到如下报错:“错误代码invalid-signature错误原因:验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配”。但展示的报错内容跟实际原因有所出入(在下文中有解答),这里记录下问题的解决排查过程。问题复现在对接电脑网站支付时,生成form表单......
  • 题解 NOIP2021 方差
    原题我认为这道题非常困难码量并不大可是需要很多次思维跳跃题意题意概述:给定非严格递增序列\(a_{n}\)可以进行若干次操作,求序列方差的最小值的\(n^2\)倍方差的定义为\(D=\frac{1}{n}\sum_{i=1}^{n}{(a_i-\bara)}^2\),其中\(\bara=\frac{1}{n}\sum_{i=1}......
  • VS 调试 提示 Lc.exe已退出 代码为-1问题解决方法
    找到程序项目下Properties文件夹licenses.licx文件,然后右键选择删除就可以了,调试运行正常了 https://jingyan.baidu.com/article/b24f6c822592b686bfe5daac.html......
  • ARC168(A-C)题解
    比赛链接:arc168A题意:读入一个由<和>构成的字符串,在最开始,最后,字符之间可以填上任意数字,任意两个相邻数字之间必须满足字符代表的大小关系。求问最后填入的数字组成的数组最少有多少对逆序对。题解:签到。<可以不去考虑,因为不会对答案造成影响。>如果不是在连续段内,也可以不......
  • [Codeforces] CF1475C Ball in Berland 题解
    BallinBerland-洛谷题意在毕业典礼上,有​个男孩和​个女孩准备跳舞,不是所有的男孩和女孩都准备结伴跳舞。现在你知道​个可能的舞伴,你需要选择其中的两对,以便使没有人重复地出现在舞伴里,求可能的数量。思路暴力最朴素,也是简单的方法,就是通过暴力组合进行配对。#include......