题解:AT_abc467_f

共 766 字
7 分钟
0 次阅读

最后一分钟场切。

首先我们知道答案按 $B$ 降序排序一定最优。证明?扔个官方证明吧。

:::success[证明]

假设按顺序 $P_1,P_2,\dots,P_N$ 给公司写信是最优的。
假设对某个 $i$ 有 $B_{P_i} \lt B_{P_{i+1}}$。
令 $S=\sum_{j=1}^{i-1}{A_{P_j}}$。
交换 $P_i$ 和 $P_{i+1}$ 后,公司 $P_i$ 收到邮件的时间从 $S+A_{P_i}+B_{P_i}$ 变为 $S+A_{P_{i+1}}+A_{P_i}+B_{P_i}$,
公司 $P_{i+1}$ 收到邮件的时间从 $S+A_{P_{i+1}}+B_{P_{i+1}}$ 变为 $S+A_{P_{i+1}}+A_{P_i}+B_{P_{i+1}}$。

$\max(S+A_{P_i}+B_{P_i},S+A_{P_i}+A_{P_{i+1}}+B_{P_{i+1}}) \ =S+A_{P_i}+A_{P_{i+1}}+B_{P_{i+1}}\ \gt \max(S+A_{P_{i+1}}+A_{P_i}+B_{P_i},S+A_{P_{i+1}}+B_{P_{i+1}}),$
因此交换后不会增加收到所有邮件所需的时间。我们还看到,若 $B_{P_i}=B_{P_{i+1}}$,则交换 $P_i$ 和 $P_{i+1}$ 不影响所需时间。因此,按 $B$ 的降序写信是最优的。

:::

设最优顺序为 $p_1,p_2,p_3,\ldots,p_n$。

现在考虑对于一个询问,答案即

$$\max_{i=1}^n [(\sum_{j=1}^{i-1}B_{p_j}) + A_{p_i}]$$

发现式子里竟然有区间最大值!同时我们又要进行单点修改,不妨使用线段树。

考虑节点维护以下信息:

  • $maxv$:区间答案

  • $sum$:区间元素和

两个节点信息合并:

$$sum=sum_L+sum_R$$$$maxv=\max(maxv_L,sum_L+maxv_R)$$

由于 $B_i$ 比较大,还需要离散化。但这引入了一个新问题:由于修改 2 可能导致 $B_i$ 在排序后的数组中的位置移动,我们还需要在离散化的时候顺便把操作 2 可能用到的位置也预留下来。

:::success[code]

使用了 AtCoder Library。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<bits/stdc++.h>
#include<atcoder/segtree>
using namespace std;
using namespace atcoder;
typedef long long ll;
struct ND{
	ll sum,maxv;
}; 
ND op(ND x,ND y){
	return {x.sum+y.sum,max(x.sum+y.maxv,x.maxv)}; 
}
ND e(){
	return {0,0};
}
int n,q,m;
int a[100005],b[100005];
bool cmp(pair<ll,int> a,pair<ll,int> b){
	if(a.first!=b.first)return a.first>b.first;
	return a.second>b.second;
}
struct QUERY{
	int op,i;
	ll x;
}que[100005];
vector<pair<ll,int> > ys;
int getpos(ll b,int id){
	ll t=lower_bound(ys.begin(),ys.end(),make_pair(b,id),greater<pair<ll,int> >())-ys.begin();
	return t;
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)scanf("%d",a+i);
	for(int i=1;i<=n;i++)scanf("%d",b+i);
	for(int i=1;i<=n;i++)ys.push_back({b[i],i});
	for(int i=1;i<=q;i++){
		scanf("%d%d%lld",&que[i].op,&que[i].i,&que[i].x);
		if(que[i].op==2)ys.push_back({que[i].x,que[i].i});
	}
	sort(ys.begin(),ys.end(),cmp);
	ys.erase(unique(ys.begin(),ys.end()),ys.end());
	m=ys.size();
	segtree<ND,op,e>seg(m);
	for(int i=1;i<=n;i++){
		int pos=getpos(b[i],i);
		seg.set(pos,{a[i],a[i]+b[i]});
	}
	for(int i=1;i<=q;i++){
		int qi=que[i].i;
		ll qx=que[i].x;
		if(que[i].op==1){
			a[qi]=qx;
			int pos=getpos(b[qi],qi);
			seg.set(pos,{a[qi],a[qi]+b[qi]});
		}else{
			int pos=getpos(b[qi],qi);
			seg.set(pos,e());
			b[qi]=qx;
			pos=getpos(b[qi],qi);
			seg.set(pos,{a[qi],a[qi]+b[qi]});
		}
		printf("%lld\n",seg.all_prod().maxv);
	}
	return 0;
}

:::

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计