分块学习笔记

分块学习笔记

区间加:

对于每个区间 \([l,r]\),如果 \(lid=rid\),那么就暴力加。否则中间块加到 \(sum[i]\)\(tag[i]\) 内,其余散块暴力加到 \(a[i]\) 内。注意不会存在最后一个块长不为 \(len\) 的情况,因为 \(rid-1\) 总是不会在最后一个块内。

区间和:

对于每个区间 \([l,r]\),如果 \(lid=rid\),那么就暴力查,加的是 \(a[i]\)\(tag[i]\)。否则中间块直接加 \(sum[id]\),左右散块暴力加 \(a[i]\)\(tag[i]\)。记得处处取模。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+7;
int tag[N],belongs[N],cnt,a[N],sum[N];
int len;
int n;
void add(int l,int r,int x){
	int lid=belongs[l],rid=belongs[r];
	if(lid==rid){
		for(int i=l;i<=r;i++) a[i]+=x,sum[lid]+=x;
		return;
	}
	for(int i=l;belongs[i]==lid;i++) a[i]+=x,sum[lid]+=x;
	for(int i=lid+1;i<rid;i++) tag[i]+=x,sum[i]+=len*x;
	for(int i=r;belongs[i]==rid;i--) a[i]+=x,sum[rid]+=x;
}
int query(int l,int r,int p){
	int lid=belongs[l],rid=belongs[r];
	int ans=0;
	if(lid==rid){
		for(int i=l;i<=r;i++) ans+=a[i],ans%=p,a[i]+=tag[lid],ans%=p;
		return ans%p;
	}
	for(int i=l;belongs[i]==lid;i++) ans+=a[i],ans%=p,ans+=tag[lid],ans%=p;
	for(int i=lid+1;i<rid;i++) ans+=sum[i],ans%=p;
	for(int i=r;belongs[i]==rid;i--) ans+=a[i],ans%=p,ans+=tag[rid],ans%=p;
	return ans%p;
}
signed main(){
	// freopen("data.in","r",stdin);
	scanf("%lld",&n);
	len=sqrt(n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		belongs[i]=(i-1)/len+1;
		sum[belongs[i]]+=a[i]; 
	}
	for(int i=1;i<=n;i++){
		int op,l,r,c;
		scanf("%lld%lld%lld%lld",&op,&l,&r,&c);
		if(op==0) add(l,r,c);
		else printf("%lld\n",query(l,r,c+1));
	}
	return 0;
}

整除分块

#include<bits/stdc++.h>
using namespace std;
#define int long long
int division_block(int n){
	int res=0;
	for(int l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		res+=n/l*(r-l+1);
	}
	return res;
}
int n;
signed main(){
	cin>>n;
	printf("%lld",division_block(n));
	return 0;
}

根号算法优化DP

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+7;
const int mod=1e9+7;
const int MAXN=2e3+7;
int f[MAXN][N];
int n,k;
int cnt,block_len[N];
void init(){
	for(int l=1,r;l<=n;l=r+1){
		r=n/(n/l),block_len[++cnt]=r-l+1; 
	}
}
signed main(){
	cin>>n>>k;
	init();
	for(int i=1;i<=cnt;i++) f[0][i]=1;
	for(int i=1;i<=k;i++){
		for(int j=1;j<=cnt;j++)
			f[i][j]=(f[i][j]+(block_len[j]*f[i-1][cnt-j+1]%mod)%mod)%mod;
		for(int j=1;j<=cnt;j++)
			f[i][j]=(f[i][j]+f[i][j-1]%mod)%mod;
	}
	printf("%lld",f[k][cnt]%mod);
	return 0;
}

根号

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;

int n,m,ans;
int d[N],A[N],B[N],vis[N];
vector<int> G[N];

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&A[i],&B[i]);
		++d[A[i]],++d[B[i]];
	}
	for(int i=1;i<=m;i++){
		int u=A[i],v=B[i];
		if(d[u]>d[v]) swap(u,v);
		else if(d[u]==d[v]&&u>v) swap(u,v);
		G[u].push_back(v); 
	}
	for(int u=1;u<=n;u++){
		for(int v:G[u]) vis[v]=u;
		for(int v:G[u]){
			for(int w:G[v]) if(vis[w]==u) ++ans;
		}
	}
	printf("%d",ans);
	return 0;
} 
posted @ 2023-07-18 20:55  Zimo_666  阅读(9)  评论(0编辑  收藏  举报