2024-4-4 分塊補題

KnightL發表於2024-04-04

P3203 [HNOI2010] 彈飛綿羊

記錄每個位置跳出當前塊所需要的步數和跳出的位置。
從後往前統計

#include<bits/stdc++.h> 
#define maxn 200100

using namespace std;

int n,m,len;
int pos[maxn],k[maxn];
int nxt[maxn],stp[maxn];
struct fk{int l,r;}a[maxn]; 

int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*w;
}

void init(){
	len=sqrt(n);
	for(int i=0;i<n;i++) pos[i]=i/len;
	for(int i=0;i<=pos[n-1];i++){
		a[i].l=i*len;
		a[i].r=(i+1)*len-1;
	}
	a[pos[n-1]].r=n-1;
}

void work(int l,int r){
	for(int i=r;i>=l;i--){
        if(i+k[i]>a[pos[i]].r){
            nxt[i]=i+k[i];
            stp[i]=1;
        } 
		else{
            nxt[i]=nxt[i+k[i]];
            stp[i]=stp[i+k[i]]+1;
        }
    }
}

int main(){
	n=read();
	for(int i=0;i<n;i++) k[i]=read();
	init();work(0,n-1);m=read();
	for(int i=1,opt,x,y,ans,p;i<=m;i++){
		opt=read();x=read();
		if(opt==1){
			p=x,ans=0;
			while(p<n) ans+=stp[p],p=nxt[p];
			cout<<ans<<endl;
		}
		else{
			y=read();k[x]=y;
			work(a[pos[x]].l,a[pos[x]].r);
		}
	}
	return 0;
}

P4168 [Violet] 蒲公英

存下每種顏色出現的位置,處理塊與塊中的眾數。
注意離散化。
計數時,中間的塊直接記錄,兩邊零散位置暴力掃。

#include<bits/stdc++.h>
#define maxn 100010
using namespace std;

int n,id,l,r,sum,res,m,las,o;
int a[maxn],num[maxn],pos[maxn];
int cnt[maxn],f[3010][3010],b[maxn];
vector<int>l1[maxn];
map<int,int>mp;

int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*w;
}

int getans(int ll,int rr,int x){
	return upper_bound(l1[x].begin(),l1[x].end(),rr)-lower_bound(l1[x].begin(),l1[x].end(),ll);
}

void init(int x){
	memset(cnt,0,sizeof(cnt));
	int maxx=0,num1=0;
	for(int i=(x-1)*m+1;i<=n;i++){
		cnt[a[i]]++;
		if(cnt[a[i]]>maxx||(cnt[a[i]]==maxx&&a[i]<num1))
			maxx=cnt[a[i]],num1=a[i]; 
		f[x][pos[i]]=num1;
	}
}

int ask(int l1,int r1){
	int maxx=0,num1=0;
	if(pos[l1]+1<pos[r1])
		maxx=getans(l1,r1,f[pos[l1]+1][pos[r1]-1]),num1=f[pos[l1]+1][pos[r1]-1]; 
	for(int i=l1;i<=min(r1,pos[l1]*m);i++) {
		res=getans(l1,r1,a[i]);
		if(res>maxx||(res==maxx&&a[i]<num1))
			maxx=res,num1=a[i];
	}
	if(pos[l1]!=pos[r1]){
		for(int i=(pos[r1]-1)*m+1;i<=r1;i++){
			res=getans(l1,r1,a[i]);
			if(res>maxx||(res==maxx&&a[i]<num1))
				maxx=res,num1=a[i];
		}
	}
	return num[num1];
}
int main(){
	n=read();o=read();
	for(int i=1;i<=n;i++) a[i]=read(),b[i]=a[i];
	sort(b+1,b+n+1);
	for(int i=1;i<=n;i++) if(!mp[b[i]])
		id++,mp[b[i]]=id,num[id]=b[i];
	for(int i=1;i<=n;i++)
		a[i]=mp[a[i]],l1[a[i]].push_back(i); 
	for(int i=1;i<=id;i++) l1[i].push_back(n+1);
	m=sqrt(n);
	for(int i=1;i<=n;i++) pos[i]=(i-1)/m+1;
	sum=pos[n];
	for(int i=1;i<=sum;i++) init(i);
	for(int i=1;i<=o;i++){
		l=read();r=read();
		l=(l+las-1)%n+1,r=(r+las-1)%n+1;
		if(l>r) swap(l,r);las=ask(l,r);
		cout<<las<<endl;
	}
	return 0;
}

相關文章