Loading

【题解】CF1476G Minimum Difference

莫队模板题。

首先这个问题不弱于带修数颜色,所以考虑带修莫队。

同时 \(cnt\) 的取值不超过 \(\sqrt{n}\) 种,所以我们可以用链表维护出现的 \(cnt\) 取值。

对于每次询问,将这 \(\sqrt{n}\)\(cnt\) 从小到大排序,答案就是最短的连续一段满足出现次数之和 \(\ge k\)

我们从小到大枚举右端点,左端点单调,直接双指针即可。

时间复杂度 \(\mathcal{O}(n^{\frac{5}{3}}+m\sqrt{n}\log\sqrt{n})\),基数排序可以做到 \(\mathcal{O}(n^\frac{5}{3}+m\sqrt{n})\)

前者手算一下大概 \(6\times 10^8\) 运算,实测 \(2s\) 毫无压力。

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define pre(i,a,b) for(register int i=a;i>=b;i--)
#define N 100005
using namespace std;
int n,m,a[N],bas,t,T,p[N],u[N],c[N],f[N],nxt[N],pre[N],ans[N],sta[N];
struct node{
	int op,x,l,r,id;
	bool operator<(const node o)const{
		if(l/bas!=o.l/bas)return l<o.l;
		if(r/bas!=o.r/bas)return r<o.r;
		return id<o.id;
	}
}q[N];
inline void rem(int x){
	if(!x)return;
	pre[nxt[x]]=pre[x];
	nxt[pre[x]]=nxt[x];
}
inline void add(int x){
	if(!x)return;
	pre[nxt[0]]=x;
	nxt[x]=nxt[0];
	pre[x]=0;nxt[0]=x;
}
inline void ins(int x){
	c[f[x]]--;
	if(!c[f[x]])rem(f[x]);
	f[x]++;
	if(!c[f[x]])add(f[x]);
	c[f[x]]++;
}
inline void del(int x){
	c[f[x]]--;
	if(!c[f[x]])rem(f[x]);
	f[x]--;
	if(!c[f[x]])add(f[x]);
	c[f[x]]++;
}
inline int calc(int k){
	register int top=0,sum=0,cur=nxt[0],ed=0x3f3f3f3f;
	while(cur)sta[++top]=cur,cur=nxt[cur];
	sort(sta+1,sta+top+1);int j=1;
	rep(i,1,top){
		sum+=c[sta[i]];
		while(sum-c[sta[j]]>=k)sum-=c[sta[j++]];
		if(sum>=k)ed=min(ed,sta[i]-sta[j]);
	} 
	if(ed==0x3f3f3f3f)return ~0;
	return ed;
}
char buf[1<<22],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read(){
    int x=0;char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return x;
}
int main(){
	bas=pow(n=read(),0.666666);m=read();
	rep(i,1,n)a[i]=read();
	rep(i,1,m){
		if(read()==1){
			++t;q[t].op=t,q[t].l=read(),q[t].r=read(),q[t].x=read(),q[t].id=T;
		}
		else{
			++T;p[T]=read(),u[T]=read();
		}
	}
	sort(q+1,q+t+1);
	register int l=1,r=1,tm=0;ins(a[1]);
	rep(i,1,t){
		while(l>q[i].l)ins(a[--l]);
		while(r<q[i].r)ins(a[++r]);
		while(l<q[i].l)del(a[l++]);
		while(r>q[i].r)del(a[r--]);
		while(tm<q[i].id){
			++tm;
			if(p[tm]>=l&&p[tm]<=r)del(a[p[tm]]),ins(u[tm]);
			swap(a[p[tm]],u[tm]);
		}
		while(tm>q[i].id){
			if(p[tm]>=l&&p[tm]<=r)del(a[p[tm]]),ins(u[tm]);
			swap(a[p[tm]],u[tm]),tm--;
		}
		ans[q[i].op]=calc(q[i].x);
	}
	rep(i,1,t)printf("%d\n",ans[i]);
	return 0;
}
posted @ 2021-10-04 17:07  7KByte  阅读(60)  评论(0编辑  收藏  举报