博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

spy(主席树)

题目链接

题目为某次雅礼集训...


对于max{aAi, Aia, bBi, Bib}max{aAi, Aia, bBi, Bib},令x1=a+b2, y1=ab2, x2=Ai+Bi2, y2=AiBi2x1=a+b2, y1=ab2, x2=Ai+Bi2, y2=AiBi2,那么maxmax就可以写成max{x1x2+y1y2, (x1x2)(y1y2), x1x2(y1y2), (x1x2)+y1y2}max{x1x2+y1y2, (x1x2)(y1y2), x1x2(y1y2), (x1x2)+y1y2}
注意到两项的正负都取到了,我们就可以写成±(x1x2)±(y1y2)=|x1x2|+|y1y2|。两项是独立的了,我们可以分别算。
x2,y2是确定的,现在要确定一个x1,y1,使得|x1x2,i|+|y1y2,i|最小(确定出x1,y1我们显然可以确定出a,b)。
这个问题...考虑一个问题:数轴上有些点,选择一个位置使得它到所有点的距离和最小,就是min{|pxi|},我们取中位数就可以了。
对于|x1x2,i|,同样取x2的中位数就可以了。区间中位数可以用主席树求。

懒得离散化了...


//6026ms	137.211MiB
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5;

int A[N],B[N],root1[N],root2[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
	#define ls son[x][0]
	#define rs son[x][1]
	#define S N*35
	int tot,sz[S],son[S][2];
	LL ans,sum[S];
	#undef S
	void Insert(int &x,int y,int l,int r,int p)
	{
		sz[x=++tot]=sz[y]+1, sum[x]=sum[y]+p;
		if(l==r) return;
		int m=(LL)l+r>>1;//LL!
		p<=m?(rs=son[y][1],Insert(ls,son[y][0],l,m,p)):(ls=son[y][0],Insert(rs,son[y][1],m+1,r,p));
	}
	int Query(int x,int y,int l,int r,int k)//x-y
	{
		if(l==r) return l;
		int m=(LL)l+r>>1,mid,t=sz[ls]-sz[son[y][0]];
		if(t>=k)
			mid=Query(ls,son[y][0],l,m,k), ans+=sum[rs]-sum[son[y][1]]-1ll*mid*(sz[rs]-sz[son[y][1]]);
		else
			mid=Query(rs,son[y][1],m+1,r,k-t), ans+=1ll*mid*(sz[ls]-sz[son[y][0]])-(sum[ls]-sum[son[y][0]]);
		return mid;
	}
}T1,T2;

inline int read()
{
	int now=0,f=1;register char c=gc();
	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now*f;
}

int main()
{
//	freopen("spy.in","r",stdin);
//	freopen("spy.out","w",stdout);

	#define S1 L1,R1
	#define S2 L2,R2
	int n=read(),q=read(),mnA=1e9,mxA=-1e9,mnB=1e9,mxB=-1e9;
	for(int i=1; i<=n; ++i) A[i]=read(),mnA=std::min(mnA,A[i]),mxA=std::max(mxA,A[i]);
	for(int i=1; i<=n; ++i) B[i]=read(),mnB=std::min(mnB,B[i]),mxB=std::max(mxB,B[i]);
	int L1=mnA+mnB,R1=mxA+mxB,L2=mnA-mxB,R2=mxA-mnB;
	for(int i=1; i<=n; ++i) T1.Insert(root1[i],root1[i-1],S1,A[i]+B[i]), T2.Insert(root2[i],root2[i-1],S2,A[i]-B[i]);
	for(; q--; )
	{
		int l=read(),r=read(),p=r-l+2>>1;
		T1.ans=0, T2.ans=0, T1.Query(root1[r],root1[l-1],S1,p), T2.Query(root2[r],root2[l-1],S2,p);
		printf("%.2lf\n",(T1.ans+T2.ans)*0.5);
	}

	return 0;
}
posted @   SovietPower  阅读(303)  评论(2编辑  收藏  举报
编辑推荐:
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示