模板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;
}

浙公网安备 33010602011771号