模板2——数据结构

ST表

PID:P3865

//P3865 【模板】ST 表 & RMQ 问题
#include<bits/stdc++.h>
using namespace std;
int n,m,l,r,st[20][1000005],lg[1000005];
//st[i][j] [j,j+(1<<i)-1]的最大值 
void init(){
	lg[1]=0;//2^0==1
	for(int i=2;i<=100000;i++) lg[i]=lg[i/2]+1;//计算最接近2的指数
	
	for(int k=1;k<=lg[n];k++)
	for(int j=1;j+(1<<k)-1<=n;j++){
		st[k][j]=max(st[k-1][j],st[k-1][j+(1<<(k-1))]);
		// [j,j+(1<<k)-1]->[j,j+(1<<(k-1))-1],[j+(1<<(k-1)),j+(1<<k)-1]
	}
		
}
int RMQ_ST(int l,int r){
	int k=lg[r-l+1];//求当前最接近的st表层数(向下取整)
	return max(st[k][l],st[k][r-(1<<k)+1]);//求此区间最大值 
}
signed main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) cin>>st[0][i];
	init();//初始化
	while(m--){
		scanf("%d%d",&l,&r);
		printf("%d\n",RMQ_ST(l,r));
	}
	return 0;
}

树状数组

PID:P3374

//P3374 【模板】树状数组 1
#include<bits/stdc++.h> 
#define int long long
using namespace std;
int  n,m,a[1001000],c[1001000];
int lowbit(int x){return x&(-x);}
void update(int i,int k){
	for(;i<=n;i+=lowbit(i)) c[i]+=k;
}
int getsum(int i){
	int ans=0;
	for(;i>0;i-=lowbit(i)) ans+=c[i];
	return ans;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		update(i,a[i]);
	}
	for(int i=1,op,j,k;i<=m;i++){
		cin>>op>>j>>k;
		if(op==1) update(j,k);
		else cout<<getsum(k)-getsum(j-1)<<"\n";
	}
	return 0;
}

另一个板子题:P3368

线段树

PID:P3372

//P3372 【模板】 线段树1
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct tree{int l,r,sum,lz;}tr[400010];
int n,m,f,a[100010];
void build(int p,int l,int r){
	tr[p].l=l,tr[p].r=r,tr[p].lz=0;
	if(l==r){
		tr[p].sum=a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build((p<<1)+1,mid+1,r);
	tr[p].sum=tr[p<<1].sum+tr[(p<<1)+1].sum;
}
void uplz(int p,int lz){
	tr[p].lz+=lz;
	tr[p].sum+=(tr[p].r-tr[p].l+1)*lz;
}
void pushdown(int p){
	if(tr[p].lz!=0){
		uplz(p<<1,tr[p].lz);
		uplz((p<<1)+1,tr[p].lz);
		tr[p].lz=0;
	}
}
void modify(int p,int l,int r,int b){
	if(tr[p].l>r||tr[p].r<l)return;
	if(tr[p].l>=l&&tr[p].r<=r){
		uplz(p,b);
		return;
	}
	pushdown(p);
	modify(p<<1,l,r,b);
	modify((p<<1)+1,l,r,b);
	tr[p].sum=tr[p<<1].sum+tr[(p<<1)+1].sum;
}
int query(int p,int l,int r){
	if(tr[p].l>r||tr[p].r<l)return 0;
	if(tr[p].l>=l&&tr[p].r<=r)return tr[p].sum;
	pushdown(p);
	return query(p<<1,l,r)+query((p<<1)+1,l,r);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,1,n);
	while(m--){
		cin>>f;
		if(f==1){
			int x,y,k;
			cin>>x>>y>>k;
			modify(1,x,y,k);
		}
		else{
			int x,y;
			cin>>x>>y;
			cout<<query(1,x,y)<<"\n";
		}
	}
	return 0;
}

另一个板子题:PID:P3373

树剖

PID:P3384

//P3384 【模板】重链剖分 / 树链剖分
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+5,INF=1e18;
struct Tree{int l,r,lz,sum;}tr[4*N];
vector<int> G[N];
int n,s,Q,M,a[N],f[N],siz[N],dep[N],sfn,id[N],rev[N],son[N],top[N];
void dfs1(int u,int fa){
	f[u]=fa;
	siz[u]=1;
	dep[u]=dep[fa]+1;
	for(auto v:G[u]){
		if(v==fa) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
}
void dfs2(int u,int t){
	top[u]=t;
	id[u]=++sfn;
	rev[sfn]=u;
	if(son[u]==0) return;
	dfs2(son[u],t);
	for(auto v:G[u]) if(v!=f[u]&&v!=son[u]) dfs2(v,v);
}
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	tr[p].sum=0;tr[p].lz=0;
	if(l==r) return;
	int mid=(l+r)/2;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
}
void uplz(int p,int x){
	tr[p].lz=(tr[p].lz%M+x%M)%M;
	tr[p].sum=(tr[p].sum%M+(tr[p].r-tr[p].l+1)*x%M)%M;
}
void pushdown(int p){
	if(tr[p].lz!=0){
		uplz(p<<1,tr[p].lz);
		uplz(p<<1|1,tr[p].lz);
		tr[p].lz=0;
	}
}
void modify(int p,int l,int r,int x){
	if(tr[p].l>r||tr[p].r<l) return;
	if(tr[p].l>=l&&tr[p].r<=r){
		uplz(p,x);
		return;
	}
	pushdown(p);
	modify(p<<1,l,r,x);
	modify(p<<1|1,l,r,x);
	tr[p].sum=(tr[p<<1].sum%M+tr[p<<1|1].sum%M)%M;
}
void modifyintree(int u,int v,int x){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		modify(1,id[top[u]],id[u],x);
		u=f[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	modify(1,id[u],id[v],x);
}
int query(int p,int l,int r){
	if(tr[p].l>r||tr[p].r<l) return 0;
	if(tr[p].l>=l&&tr[p].r<=r) return tr[p].sum%M;
	pushdown(p);
	return (query(p<<1,l,r)%M+query(p<<1|1,l,r)%M)%M;
}
int queryintree(int u,int v){
	int sum=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		sum=(sum%M+query(1,id[top[u]],id[u])%M)%M;
		u=f[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	sum=(sum%M+query(1,id[u],id[v])%M)%M;
	return sum;
}
void solve(){
	int op,u,v,x;
	cin>>op;
	if(op==1){
		cin>>u>>v>>x;
		modifyintree(u,v,x%M);
	}
	else if(op==2){
		cin>>u>>v;
		cout<<queryintree(u,v)%M<<"\n";
	}
	else if(op==3){
		cin>>u>>x;
		modify(1,id[u],id[u]+siz[u]-1,x%M);
	}
	else{
		cin>>u;
		cout<<query(1,id[u],id[u]+siz[u]-1)%M<<"\n";
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>Q>>s>>M;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1,u,v;i<n;i++){
		cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs1(s,0);
	dfs2(s,0);
	build(1,1,n);
	for(int i=1;i<=n;i++) modify(1,id[i],id[i],a[i]%M);
	while(Q--) solve();
	return 0;
}

线性基

PID:P3812

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;// 数字的个数
int a[510];// 存储输入的 n 个数(最多 500 个)
int xxj[55];// 线性基数组,下标表示二进制位(0~49 足够处理 1e18 内的数)
int ans;// 存储最终的最大异或和结果
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin >> n;
    // 构建线性基
    for(int i=1;i<=n;i++){
        cin>>a[i];// 读取每个数字
        // 将 a[i] 插入线性基中
        for(int j=49;j>=0;j--){// 从高位到低位遍历
            if((a[i]>>j)&1){// 如果 a[i] 的第 j 位是 1
                if(xxj[j]>0){// 如果线性基的第 j 位已经有值
                    a[i]^=xxj[j];//异或掉该位的基,继续尝试降低 a[i] 的最高位
                }
                else{// 如果该位置为空
                    xxj[j]=a[i];//将 a[i] 存入线性基的第 j 位
                    break;//插入完成,退出循环
                }
            }
        }
    }
    
    // 求最大异或和(贪心策略)
    for(int i=49;i>=0;i--)// 从高位到低位遍历
        if(((ans>>i)&1)==0)// 如果 ans 的第i位是0
            ans^=xxj[i];// 异或上该位的基,使得第i位变为 1(最大化结果)
    cout<<ans;
    return 0;
}
posted @ 2026-09-28 20:21  _T_M_T  阅读(6)  评论(0)    收藏  举报