CF1270H Number of Components

很好的题目。

首先容易发现连通块一定是一个区间,而这个时候就可以 \(O(nlog^2 n)\) 解决了,具体就是用线段树维护,对于线段树上的节点维护其最左边的连通块的最大值,最右边的连通块的最小值,然后考虑 \(O(log n)\) 合并即可。

但还有更奇妙的做法,就是考虑每个连通块的断点 \(x\),一定是 \(\min_{i=1}^{x} a_i \ge \max_{i=x+1}^{n} a_i\),考虑这个后缀最大值的值为 \(w\),若将序列变成 $[a_i \ge w] $,那一定是一个形如 \(11111..100000\) 的序列,也就是说这个 \(01\) 序列只有两个连通块,所以对于相邻的两个数 \(a_i\)\(a_{i+1}\)\(w\) 在 $[\min(a_i,a_{i+1}),\max(a_i,a_{i+1})) $ 中才会出现一个 \(01\)

然后用一棵权值线段树维护 \(01\) 个数为 \(1\)\(w\) 的个数即可。

点击查看代码
#include<bits/stdc++.h>
#define fir first
#define sec second
#define int long long
#define pir pair<int,int>
#define mkp(a,b) make_pair(a,b)
using namespace std;
inline int read(){
	int x=0,f=1; char c=getchar();
	while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
	return x*f;
}
const int mod=998244353,inf=1e9,N=5e5+5,V=1e6+5,lim=1e6;
int n,q,a[N];
struct tree{
	int mn[V<<2],res[V<<2],tg[V<<2];
	inline void push_up(int p){
		mn[p]=min(mn[p<<1],mn[p<<1|1]);
		res[p]=(mn[p<<1]==mn[p])*res[p<<1]+(mn[p<<1|1]==mn[p])*res[p<<1|1];
	}
	inline void modify(int p,int k){tg[p]+=k,mn[p]+=k;}
	inline void push_down(int p){if(tg[p]) modify(p<<1,tg[p]),modify(p<<1|1,tg[p]),tg[p]=0;}
	inline void upd(int l,int r,int p,int ll,int rr,int k){
		if(ll<=l&&r<=rr){modify(p,k);return ;}
		int mid=(l+r)>>1;
		push_down(p);
		if(ll<=mid) upd(l,mid,p<<1,ll,rr,k);
		if(rr>mid)  upd(mid+1,r,p<<1|1,ll,rr,k);
		push_up(p); 
	}
	inline void add(int l,int r,int p,int num,int k){
		assert(l<=num&&num<=r);
		if(l==r){res[p]+=k; return ;}
		int mid=(l+r)>>1;
		push_down(p);
		if(num<=mid) add(l,mid,p<<1,num,k);
		else add(mid+1,r,p<<1|1,num,k);
		push_up(p);
	}
}T;
inline void change(int x,int k){T.upd(0,lim,1,min(a[x],a[x+1]),max(a[x],a[x+1])-1,k);}
signed main(){
	n=read(),q=read();
	a[0]=inf,a[n+1]=0;
	for(int i=1;i<=n;i++) a[i]=read(),T.add(0,lim,1,a[i],1);
	for(int i=0;i<=n;i++) change(i,1);
	while(q--){
		int x=read(),k=read();
		T.add(0,lim,1,a[x],-1),change(x-1,-1),change(x,-1);
		a[x]=k;
		T.add(0,lim,1,a[x],1),change(x-1,1),change(x,1);
		cout<<T.res[1]<<'\n'; 
	}
}
/*
5 3
25 40 30 20 10
*/ 
posted @ 2024-12-04 21:20  ~Cyan~  阅读(1)  评论(0编辑  收藏  举报