BC2402C. 多重集(set)

news/2024/10/15 20:16:54

BC2402C. 多重集(set)

题意

给你两个集合 \(A,B\),开始时集合为空。有 \(n\) 次操作,每次往其中一个集合插入或者删除一个数对 \((a,b)\),保证删除的数对存在。每次操作后输出 \(\min_{x,y} \{ \max(a_x+a_y,b_x+b_y),(a_x,b_x)\in A,(a_y,b_y) \in B \}\)

思路

一个显然的优化是按照 \(a_x+a_y,b_x+b_y\) 的大小关系分类讨论,以此去除讨厌的 \(\max\)

\(a_x+a_y \ge b_x+b_y\) 时,有 \(a_x-b_x \ge -a_y + b_y\)。因此我们可以对于每一个 \(x\),对于满足 \(a_x-b_x \ge -a_y + b_y\)\(y\),取 \(\max\) 一定会取到 \(a_x+a+y\),因此对这些 \(y\)\(a\) 的最小值。对于 \(a_x-b_x < -a_y + b_y\)\(y\) 同理,求 \(b\) 的最小值。

只考虑插入操作,可以将操作离线,以 \(a_i-b_i\) 对离散化后的操作排序,相当于前缀或者后缀求最小值,以及动态插入,用线段树可以维护。

然后愚蠢的我以为求最小值不支持删除操作。大概是被莫队搞晕了。线段树本来就是支持单点甚至区间修改维护最大值和最小值的。

因此删除操作就单点删除,然后上传更新最小值即可。

时间复杂度是 \(O(n \log n)\)。主要难点在于想到对 \(\max\) 进行分类讨论(需要做题经验显然我好不容易有了然后脑抽以及不要脑抽

一种比较优美的写法是,首先线段树节点肯定要存 \(a,b\) 最小值,把两个集合的信息一个集合以 \(a_i-b_i\) 排名为下标,另一个以 \(-a_i+b_i\) 排名为下标,存在一棵树里,在线段树里维护答案。

code

感觉减少常数需要精细思考,但是代码还是很好写的。

#include<bits/stdc++.h>
// #define LOCAL
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++) 
#define per(x,y,z) for(int x=y;x>=z;x++)
using namespace std;
typedef long long ll;
constexpr int N=1e6+7;
#define isdigit(x) (x>='0'&&x<='9')
template <typename T>
void read(T &x) {x=0;char ch=getchar();for(;!isdigit(ch);ch=getchar()) ;for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
template <typename T>
void write(T x,char ch) {static int st[20];int top=0;do {st[top++]=x%10;x/=10;}while(x);while(top) putchar(st[--top]+'0');putchar(ch);
}
int q;
int cnt;
typedef unsigned int uint;
constexpr uint inf=0x7f7f7f7f;
struct pii {uint a,b;bool operator < (const pii x) const { return a!=x.a?a<x.a:b<x.b; }
};
struct node {int d;pii x;bool operator < (const node y) const { int c1=d?x.b-x.a:x.a-x.b,c2=y.d?y.x.b-y.x.a:y.x.a-y.x.b;return c1!=c2 ? c1<c2 : (d!=y.d?d<y.d:x<y.x) ;}
}t[N];
struct que{int op,d;pii x;
}qu[N];
int op,d,a,b;
struct tree {pii mn[N<<2][2]; uint tr[N<<2];tree() { memset(mn,0x7f,sizeof(mn)); memset(tr,0x7f,sizeof(tr)); }pii _min(pii x,pii y) { return {min(x.a,y.a),min(x.b,y.b)}; }void pushup(int u) {mn[u][0]=_min(mn[u<<1][0],mn[u<<1|1][0]); mn[u][1]=_min(mn[u<<1][1],mn[u<<1|1][1]);tr[u]=min(min(tr[u<<1],tr[u<<1|1]),min(mn[u<<1][1].a+mn[u<<1|1][0].a,mn[u<<1][0].b+mn[u<<1|1][1].b));}void insert(int u,int l,int r,int x,int del) {if(l==r) {if(del) memset(mn[u],0x7f,sizeof(mn[u])), tr[u]=inf;else mn[u][t[x].d]=t[x].x;return;}int mid=(l+r)>>1;if(x<=mid) insert(u<<1,l,mid,x,del);else insert(u<<1|1,mid+1,r,x,del);pushup(u);}
}T;
int main() {#ifdef LOCALfreopen("in.txt","r",stdin);freopen("my.out","w",stdout);#elsefreopen("set.in","r",stdin);freopen("set.out","w",stdout);#endifread(q);rep(i,1,q) {read(op),read(d),read(a),read(b);qu[i]={op,d,{a,b}};if(op) t[++cnt]={d,{a,b}};}sort(t+1,t+cnt+1);rep(i,1,q) {int op=qu[i].op,d=qu[i].d;pii x=qu[i].x;int pos=lower_bound(t+1,t+cnt+1,(node){d,x})-t;T.insert(1,1,cnt,pos,op==0);uint ans=T.tr[1];if(ans==inf) puts("-1");else write(ans,'\n');}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71965.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

习题3.2

def X(n): # 差分方程的解 return 2 * (-1)**(n + 1) n_values = [0, 1, 2, 3, 4, 5] for n in n_values: print(f"X({n}) = {X(n)}")print("学号:3008") 结果如下

习题2.9

import sympy as sp # 定义变量 x, y = sp.symbols(x y) # 定义方程组 equation1 = sp.Eq(x**2 - y - x, 3) equation2 = sp.Eq(x + 3*y, 2) # 解方程组 solutions = sp.solve((equation1, equation2), (x, y), dict=True) print("符号解:") for sol …

习题2.10

from scipy.integrate import quad import numpy as np # 第一部分:抛物线旋转体(修正后) def V1_quad(y): return np.pi * (4*y - y**2) V1_corrected, _ = quad(V1_quad, 1, 3) # 第二部分保持不变 V2 = 0.5 * (4/3) * np.pi * 2**3 - (1/3) * np.pi * 2**2 * 1…

开发者门户是什么?为什么企业需要它?

随着企业规模的扩大,其基础设施、服务以及API的复杂性往往增长得更为迅速。在这种增长背景下,了解现有资源并合理利用这些资源变得愈发困难。尤其是当你涉及到外部开发者和第三方应用开发者时,创建一个了解和交互基础设施、服务和API的中央平台能够节省时间并简化入门流程。…

第五周(10.8-

代码题: 1、给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 题解:如果等于nums[middle],返回middle;否则返回left或者low。 2、在排序数组中查找target的开始位置和结束位置。 二分法不可能会漏…

习题2.6

import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 模拟高程数据(假设数据已经过某种方式插值或生成) # 这里我们创建一个简单的40x50网格,并填充随机高程值 x = np.linspace(0, 43.65, 40) y = np.linspace(0, 58…

习题2.7(2)

import numpy as np # 定义系数矩阵A和常数项向量b A = np.array([[2, 3, 1], [1, -2, 4], [3, 8, -2], [4, -1, 9]]) b = np.array([4, -5, 13, -6]) # 使用numpy的lstsq函数求解最小二乘解 # 对于这个特定的问题,由于方程数和未知数数量相同,且没有矛盾,lstsq将…

习题2.4

import numpy as np import matplotlib.pyplot as plt # 定义x的范围 x = np.linspace(-10, 10, 400) # 创建一个2行3列的子图布局 fig, axs = plt.subplots(2, 3, figsize=(12, 8)) # 遍历每个子图 for k, ax in enumerate(axs.flat, start=1): y = k * x**2 + 2*…