[CSP-S 2022] 策略游戏(线段树代码)

H0ndomach1·2023-09-07 16:53·268 次阅读

[CSP-S 2022] 策略游戏(线段树代码)

[CSP-S 2022] 策略游戏

题意:#

给定两个序列A,B。每次先从A序列规定区间内取出一个数,再从B序列规定区间内取一个数,答案为两数乘积。A希望答案尽可能大,B希望答案尽可能小。

思路:#

考虑特殊性质#

  1. 保证 A1,B1>0

显然对于每次询问,A取区间最大值,B取区间最小值。
线段树或ST表维护区间最值即可。

  1. 保证每次询问有l1=r1,或l2=r2
  • 若A只有非负数--------B选择优先级为:最小负数,0, 最小正数
  • 当A为负数--------------B选择优先级为:最大正数, 0, 最小负数
  • 如果B只有非负数---- A选择优先级为:最大正数 ,0, 最小负数
  • 要是B只有负数 -------A选择优先级为:最大负数 ,0, 最小正数

此时发现如果将后方得出的选择优先级再进行分类讨论就能表示出所有的选择情况,分情况选择区间所维护的信息相乘即可。

因为0无论如何归类都不会对过程产生影响,所以把0和正数一同处理。

得出有以下几种情况:

  1. A 区间全为正数

    (1) B 区间全为正数,A 取最大, B 取最小

    (2) B 区间有正有负,A 取最小,B 取最小

    (3) B 区间全为负数,A 取最小,B 取最小

  2. A 区间有正有负

    (1) B 区间全为正数,A 取最大,B 取最小

    (2) B 区间有正有负,max(A×BA×B)

    (3) B 区间全为负数,A 取最小,B 取最大

  3. A 区间全为负数

    (1) B 区间全为正数,A 取最大,B 取最大

    (2) B 区间有正有负,A 取最大,B 取最大

    (3) B 区间全为负数,A 取最小,B 取最大

可以发现用到的信息为各区间的:

最大正数,最大负数,最小正数,最小负数。

为了方便思路也可以增加区间最大值和区间最小值两个信息。当然在AB均无特殊情况时也可以用最大正数和最小负数来代替。

所以变成了经典的区间维护最值问题,可以分别对A序列和B序列建一棵线段树,维护以上六个区间信息。

Copy
#include<bits/stdc++.h> #define MAXN 100086 #define ls p<<1 #define rs p<<1|1 #define node p #define int long long #define inf 1000000001 #define itvl1 l1,r1,1,t1//A的规定区间 #define itvl2 l2,r2,1,t2//B的规定区间 using namespace std; int n,m,q,a[MAXN],b[MAXN]; struct T{ int l,r,maxz,minz,maxf,minf;//区间左右端点,最大最小的正数(非负数),最大最小的负数 int maxn,minn;//区间最大值,区间最小值 }t1[MAXN<<2],t2[MAXN<<2]; void updata(int p,T t[]){ t[p].maxn=max(t[ls].maxn,t[rs].maxn); t[p].minn=min(t[ls].minn,t[rs].minn); t[p].maxz=max(t[ls].maxz,t[rs].maxz); t[p].minz=min(t[ls].minz,t[rs].minz); t[p].maxf=max(t[ls].maxf,t[rs].maxf); t[p].minf=min(t[ls].minf,t[rs].minf); } //l,r,maxz,minz,maxf,minf; void build(int l,int r,int p,T t[],int a[]){ t[p]={l,r}; if(l==r){ t[p].maxn=t[p].minn=a[l]; if(a[l]>=0){ t[p].maxz=t[p].minz=a[l]; t[p].minf=inf; t[p].maxf=-inf; } else{ t[p].maxf=t[p].minf=a[l]; t[p].minz=inf; t[p].maxz=-inf; } return ; } int mid=(l+r)/2; build(l,mid,ls,t,a); build(mid+1,r,rs,t,a); updata(p,t); } inline int askmax(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].maxn; } int ans=-inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=max(ans,askmax(l,r,ls,t)); if(mid<r)ans=max(ans,askmax(l,r,rs,t)); return ans; } inline int askmin(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].minn; } int ans=inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=min(ans,askmin(l,r,ls,t)); if(mid<r)ans=min(ans,askmin(l,r,rs,t)); return ans; } inline int askmaxz(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].maxz; } int ans=-inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=max(ans,askmaxz(l,r,ls,t)); if(mid<r)ans=max(ans,askmaxz(l,r,rs,t)); return ans; } inline int askminz(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].minz; } int ans=inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=min(ans,askminz(l,r,ls,t)); if(mid<r)ans=min(ans,askminz(l,r,rs,t)); return ans; } inline int askmaxf(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].maxf; } int ans=-inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=max(ans,askmaxf(l,r,ls,t)); if(mid<r)ans=max(ans,askmaxf(l,r,rs,t)); return ans; } inline int askminf(int l,int r,int p,T t[]){ if(l<=t[p].l&&t[p].r<=r){ return t[p].minf; } int ans=inf; int mid=(t[p].l+t[p].r)/2; if(l<=mid)ans=min(ans,askminf(l,r,ls,t)); if(mid<r)ans=min(ans,askminf(l,r,rs,t)); return ans; } //////////////////////// signed main(){ int f1=0,f2=0,l1,l2,r1,r2; cin>>n>>m>>q; for(int i=1;i<=n;i++){ cin>>a[i]; if(a[i]<0)f1=-1; } for(int i=1;i<=m;i++){ cin>>b[i]; if(b[i]<0)f2=-1; } build(1,n,1,t1,a); build(1,m,1,t2,b); while(q--){ cin>>l1>>r1>>l2>>r2; if(f1==0&&f2==0){//特殊性质1:AB序列都为非负数 cout<<askmax(itvl1)*askmin(itvl2)<<'\n'; continue; } int ans=-1e18+1,ans2=1e9+1,ans3=1e9+1,ans4=1e9+1; int a1=askmaxz(itvl1);//正 max int a2=askminz(itvl1);//正 min int a3=askmaxf(itvl1);//负 max int a4=askminf(itvl1);//负 min int b1=askmax(itvl2);//max int b2=askmin(itvl2);//min if(a1!=-inf) ans=max(ans,a1*b2); else ans=max(ans,a3*b1); if(a4!=inf) ans=max(ans,a4*b1); else ans=max(ans,a2*b2); if(a3!=-inf) ans=max(ans,a3*b1); if(a2!=inf) ans=max(ans,a2*b2); cout<<ans<<'\n'; } return 0; }
posted @   DAIANZE  阅读(268)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示
目录