Examples

2022-7-29 #21 P6717

今天花了点时间看完了 淤泥之花与空心石,只能说是神作了!(时长共计 12h,看的非常过瘾)

055 P6717 [CCO2018] Boring Lectures

我们将序列按照 \(k\) 分块,断言答案中至少会有一个块内最大值。

反证法,令最优决策为 \(a,b\),若在同一块,明显把较小的改为块内最大值更优;否则在相邻块,令最大值分别为 \(c,d\),有:

\[a+b>a+c,a+b>b+d\\\Rightarrow b>c,a>d \]

显然矛盾。

于是维护每一块最大值对应的匹配,放在堆里维护即可,复杂度 \(O((n+q)\log n)\)

#include<stdio.h>
#include<queue>
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid (l+r>>1)
using namespace std;
const int maxn=1000005,maxt=maxn<<2;
int n,k,T,bt,stp;
int mx[maxt],a[maxn],bel[maxn],bl[maxn],br[maxn],vis[maxn];
priority_queue< pair<int, pair<int,int> > >q;
inline void pushup(int now){
	mx[now]=a[mx[lc(now)]]>a[mx[rc(now)]]? mx[lc(now)]:mx[rc(now)];
}
void build(int l,int r,int now){
	if(l==r){
		mx[now]=l;
		return ;
	}
	build(l,mid,lc(now)),build(mid+1,r,rc(now)),pushup(now);
}
void modify(int l,int r,int now,int p){
	if(l==r)
		return ;
	if(p<=mid)
		modify(l,mid,lc(now),p);
	else modify(mid+1,r,rc(now),p);
	pushup(now);
}
int query(int l,int r,int now,int L,int R){
	if(L<=l&&r<=R)
		return mx[now];
	if(L<=mid&&mid<R){
		int ls=query(l,mid,lc(now),L,R),rs=query(mid+1,r,rc(now),L,R);
		return a[ls]>a[rs]? ls:rs;
	}
	if(L<=mid)
		return query(l,mid,lc(now),L,R);
	return query(mid+1,r,rc(now),L,R);
}
void answer(){
	while(!q.empty()&&vis[q.top().second.first]!=q.top().second.second)
		q.pop();
	printf("%d\n",q.top().first);
}
void insert(int id){
	int p=query(1,n,1,bl[id],br[id]),c=-1;
	swap(c,a[p]),modify(1,n,1,p);
	vis[id]=stp,q.push(make_pair(c+a[query(1,n,1,max(1,p-k+1),min(n,p+k-1))],make_pair(id,stp)));
	swap(c,a[p]),modify(1,n,1,p);
}
int main(){
	scanf("%d%d%d",&n,&k,&T),bt=n/k;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=bt;i++)
		bl[i]=br[i-1]+1,br[i]=i*k;
	if(br[bt]<n)
		bt++,bl[bt]=br[bt-1]+1,br[bt]=n;
	build(1,n,1);
	stp=1;
	for(int i=1;i<=bt;i++){
		for(int j=bl[i];j<=br[i];j++)
			bel[j]=i;
		insert(i);
	}
	answer();
	for(int i=1,x,y;i<=T;i++){
		scanf("%d%d",&x,&y),a[x]=y,modify(1,n,1,x);
		stp++;
		if(bel[x]>1)
			insert(bel[x]-1);
		insert(bel[x]);
		if(bel[x]<bt)
			insert(bel[x]+1);
		answer();
	}
	return 0;
}
posted @ 2022-07-29 07:50  xiaoziyao  阅读(71)  评论(0编辑  收藏  举报