树剖
戳他
平衡树
Splay
模板指路
点击查看代码
//超级全,啥都有
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,INF=0x3f3f3f3f;
struct node{
int son[2],cnt,val,tot,fa;
}tr[N];
int co,root;
int read(){
int sum=0,f=1;char a=getchar();
while(a<'0' || a>'9'){if(a=='-') f=-1;a=getchar();}
while(a>='0' && a<='9') sum=sum*10+a-'0',a=getchar();
return sum*f;
}
inline void pushup(int x){
tr[x].tot=tr[tr[x].son[0]].tot+tr[tr[x].son[1]].tot+tr[x].cnt;
}
inline void rotate(int x){
int y=tr[x].fa,z=tr[y].fa,k=(tr[y].son[1]==x);
tr[z].son[tr[z].son[1]==y]=x;
// cout<<"rotate: "<<x<<" "<<z<<" "<<tr[x].val<<" "<<tr[z].val<<endl;
tr[x].fa=z;
tr[y].son[k]=tr[x].son[k^1];
tr[tr[x].son[k^1]].fa=y;
tr[x].son[k^1]=y;
tr[y].fa=x;
pushup(y),pushup(x);
}
void splay(int x,int goal){
while(tr[x].fa!=goal){
int y=tr[x].fa,z=tr[y].fa;
if(z!=goal)
((tr[y].son[1]==x)^(tr[z].son[1]==y))?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
void fi(int x){
int u=root;
if(!u) return;
while(tr[u].son[x>tr[u].val] && tr[u].val!=x)
u=tr[u].son[x>tr[u].val];
splay(u,0);
}
void insert(int x){
int fa=0,u=root;
while(u && tr[u].val!=x){
fa=u;
u=tr[u].son[x>tr[u].val];
}
// cout<<"insert : "<<x<<" "<<u<<" "<<fa<<" "<<tr[u].val<<" "<<tr[fa].val<<endl;
if(u) tr[u].cnt++;
else{
u=++co;
if(fa) tr[fa].son[x>tr[fa].val]=u;
tr[u].fa=fa,tr[u].son[0]=tr[u].son[1]=0;
tr[u].cnt=1,tr[u].tot=1,tr[u].val=x;
}
splay(u,0);
}
int nxt(int x,bool k){
fi(x);
int u=root;
if(tr[u].val>x && k) return u;
if(tr[u].val<x && !k) return u;
u=tr[u].son[k];
while(tr[u].son[k^1]) u=tr[u].son[k^1];
return u;
}
void delet(int x){
int pre=nxt(x,0),suc=nxt(x,1);
splay(pre,0),splay(suc,pre);
int del=tr[suc].son[0];
if(tr[del].cnt>1){
tr[del].cnt--;
splay(del,0);
}
else tr[suc].son[0]=0;
}
int rk(int x){
fi(x);
return tr[tr[root].son[0]].tot+1;
}
int kth(int p,int x){
// cout<<"kth : "<<p<<" "<<tr[p].tot<<" "<<tr[p].val<<" "<<x<<endl;
if(tr[p].tot<x) return 0;
if(tr[tr[p].son[0]].tot>=x) return kth(tr[p].son[0],x);
if(tr[tr[p].son[0]].tot+tr[p].cnt>=x) return tr[p].val;
return kth(tr[p].son[1],x-tr[tr[p].son[0]].tot-tr[p].cnt);
}
int main(){
insert(-INF),insert(INF);
int n=read(),op,x;
while(n--){
op=read(),x=read();
if(op==1) insert(x);
if(op==2) delet(x);
if(op==3) printf("%d\n",rk(x)-1);
if(op==4) printf("%d\n",kth(root,x+1));
if(op==5) printf("%d\n",tr[nxt(x,0)].val);
if(op==6) printf("%d\n",tr[nxt(x,1)].val);
}
return 0;
}
线段树
单点加减,区间询问
模板
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int N=1e5+5;
int tr[N<<2];
void pushup(int node){
tr[node]=tr[node<<1]+tr[node<<1|1];
}
void change(int node,int l,int r,int x,int y){
if(l>x || r<x) return;
if(l==r && l==x){
tr[node]+=y;
return;
}
change(node<<1,l,mid,x,y);
change(node<<1|1,mid+1,r,x,y);
pushup(node);
}
int ask(int node,int l,int r,int be,int en){
if(l>en || r<be) return 0;
if(l>=be && r<=en) return tr[node];
return ask(node<<1,l,mid,be,en)+ask(node<<1|1,mid+1,r,be,en);
}
int main(){
int n,m;
cin>>n>>m;
while(m--){
int op,x,y;
cin>>op>>x>>y;
if(op) cout<<ask(1,1,n,x,y)<<endl;
else change(1,1,n,x,y);
}
return 0;
}
区间加减,区间询问
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define int long long
const int N=1e6+5;
int tr[N<<2],lz[N<<2],len[N<<2];
int read(){
int sum=0,f=1;char a=getchar();
while(a<'0' || a>'9'){if(a=='-') f=-1;a=getchar();}
while(a>='0' && a<='9') sum=sum*10+a-'0',a=getchar();
return sum*f;
}
void print(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
void pushup(int node){
tr[node]=tr[node<<1]+tr[node<<1|1];
}
void push(int node,int x){
tr[node]+=len[node]*x,lz[node]+=x;
}
void pushdown(int node){
if(lz[node]){
push(node<<1,lz[node]);
push(node<<1|1,lz[node]);
lz[node]=0;
}
}
void build(int node,int l,int r){
len[node]=r-l+1;
if(l==r){
tr[node]=read();
return;
}
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
pushup(node);
}
void change(int node,int l,int r,int be,int en,int x){
if(l>en || r<be) return;
if(l>=be && r<=en){
push(node,x);
return;
}
pushdown(node);
change(node<<1,l,mid,be,en,x);
change(node<<1|1,mid+1,r,be,en,x);
pushup(node);
}
int ask(int node,int l,int r,int be,int en){
if(l>en || r<be) return 0;
if(l>=be && r<=en) return tr[node];
pushdown(node);
return ask(node<<1,l,mid,be,en)+ask(node<<1|1,mid+1,r,be,en);
}
signed main(){
int n,m;
n=read(),m=read();
build(1,1,n);
while(m--){
int op,x,y,z;
op=read(),x=read(),y=read();
if(op==2) print(ask(1,1,n,x,y)),puts("");
else z=read(),change(1,1,n,x,y,z);
}
return 0;
}
区间加乘,区间询问
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define int long long
const int N=1e5+5;
int p;
int tr[N<<2],lz_add[N<<2],lz_mul[N<<2],len[N<<2];
int read(){
int sum=0,f=1;char a=getchar();
while(a<'0' || a>'9'){if(a=='-') f=-1;a=getchar();}
while(a>='0' && a<='9') sum=sum*10+a-'0',a=getchar();
return sum*f;
}
void pushup(int node){
tr[node]=(tr[node<<1]%p+tr[node<<1|1]%p)%p;
}
void push_add(int node,int x){
tr[node]+=len[node]*x,tr[node]%=p;
lz_add[node]+=x,lz_add[node]%=p;
}
void push_mul(int node,int x){
tr[node]*=x,tr[node]%=p;
lz_mul[node]*=x,lz_mul[node]%=p;
lz_add[node]*=x,lz_add[node]%=p;
}
void pushdown(int node){
if(lz_mul[node]!=1){
push_mul(node<<1,lz_mul[node]);
push_mul(node<<1|1,lz_mul[node]);
lz_mul[node]=1;
}
if(lz_add[node]){
push_add(node<<1,lz_add[node]);
push_add(node<<1|1,lz_add[node]);
lz_add[node]=0;
}
}
void build(int node,int l,int r){
len[node]=r-l+1;
lz_mul[node]=1;
if(l==r){
tr[node]=read()%p;
return;
}
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
pushup(node);
}
void change_mul(int node,int l,int r,int be,int en,int x){
if(l>en || r<be) return;
if(l>=be && r<=en){
push_mul(node,x);
return;
}
pushdown(node);
change_mul(node<<1,l,mid,be,en,x);
change_mul(node<<1|1,mid+1,r,be,en,x);
pushup(node);
}
void change_add(int node,int l,int r,int be,int en,int x){
if(l>en || r<be) return;
if(l>=be && r<=en){
push_add(node,x);
return;
}
pushdown(node);
change_add(node<<1,l,mid,be,en,x);
change_add(node<<1|1,mid+1,r,be,en,x);
pushup(node);
}
int ask(int node,int l,int r,int be,int en){
if(l>en || r<be) return 0;
if(l>=be && r<=en) return tr[node]%p;
pushdown(node);
return (ask(node<<1,l,mid,be,en)+ask(node<<1|1,mid+1,r,be,en))%p;
}
signed main(){
int n,m;
n=read(),p=read();
build(1,1,n);
m=read();
while(m--){
int op,x,y,z;
op=read(),x=read(),y=read();
if(op==1) z=read(),change_mul(1,1,n,x,y,z);
if(op==2) z=read(),change_add(1,1,n,x,y,z);
if(op==3) printf("%lld\n",ask(1,1,n,x,y));
}
return 0;
}
扫描线
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mid ((l+r)>>1)
const int N=2e5+5;
int ly[N];
struct seg{
int x,y[2];
int val;
}a[N];
int len[N<<4],tr[N<<4],sum[N<<4];
inline int read(){
int sum=0,f=1;char a=getchar();
while(a<'0' || a>'9'){if(a=='-') f=-1;a=getchar();}
while(a>='0' && a<='9') sum=sum*10+a-'0',a=getchar();
return sum*f;
}
bool cmp(seg _,seg __){
return _.x<__.x;
}
void build(int node,int l,int r){
len[node]=ly[r+1]-ly[l];
if(l==r) return;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
}
void pushup(int node){
if(sum[node])
tr[node]=len[node];
else
tr[node]=tr[node<<1]+tr[node<<1|1];
}
void change(int node,int l,int r,int be,int en,int x){
if(l>en || r<be) return;
if(l>=be && r<=en){
sum[node]+=x;
pushup(node);
return;
}
change(node<<1,l,mid,be,en,x);
change(node<<1|1,mid+1,r,be,en,x);
pushup(node);
}
signed main(){
int n=read();
for(int i=1;i<=n;++i){
a[i].x=read(),a[i].y[0]=a[i+n].y[0]=ly[i]=read();
a[i+n].x=read(),a[i].y[1]=a[i+n].y[1]=ly[i+n]=read();
a[i].val=1,a[i+n].val=-1;
}
n*=2;
sort(a+1,a+n+1,cmp);
sort(ly+1,ly+n+1);
int co=unique(ly+1,ly+n+1)-ly-1;
ly[co+1]=0x3f3f3f3f;
build(1,1,co);
int ans=0;
for(int i=1;i<n;++i){
int y=lower_bound(ly+1,ly+co+1,a[i].y[0])-ly;
int y1=lower_bound(ly+1,ly+co+1,a[i].y[1])-ly-1;
//cout<<y<<" "<<y1<<endl;
change(1,1,co,y,y1,a[i].val);
ans+=tr[1]*(a[i+1].x-a[i].x);
//cout<<a[i].x<<" "<<a[i].val<<" "<<ans<<endl;
}
printf("%lld",ans);
return 0;
}
树状数组
区间加减,区间询问
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
#define int long long
int read(){
int sum=0,f=1;char a=getchar();
while(a<'0'||a>'9'){if(a=='-')f=-1;a=getchar();}
while(a>='0'&&a<='9')sum=sum*10+a-'0',a=getchar();
return sum*f;
}
int n,q;int a[N];
struct bit{
int a[N];
bit(){memset(a,0,sizeof a);}
void add(int x,int y){for(int i=x;i<=n;i+=(i&-i))a[i]+=y;}
int ask(int x){
if(x<=0)return 0;int res=0;
for(int i=x;i;i-=(i&-i))res+=a[i];
return res;
}
}b,c;
int ask(int x){return (x+1)*b.ask(x)-c.ask(x);}
signed main(){
n=read(),q=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)b.add(i,a[i]-a[i-1]),c.add(i,(a[i]-a[i-1])*i);
while(q--){
int opt=read(),l=read(),r=read(),x;
if(opt==1){
x=read();
b.add(l,x),b.add(r+1,-x);
c.add(l,x*l),c.add(r+1,-x*(r+1));
}
else printf("%lld\n",ask(r)-ask(l-1));
}
return 0;
}
字典树
可持久化 01 Trie
模板
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
struct node{
int cnt,s[2];
}t[N*35];
int co;
int rt[N];
void insert(int p,int q,int x){
for(int i=30;i>=0;--i){
t[p].cnt=t[q].cnt+1;
bool w=(x&(1<<i));
if(!t[p].s[w]) t[p].s[w]=++co;
t[p].s[w^1]=t[q].s[w^1];
p=t[p].s[w],q=t[q].s[w];
}
t[p].cnt=t[q].cnt+1;
}
int ask(int p,int q,int x){
int res=0;
for(int i=30;i>=0;--i){
bool w=(x&(1<<i));
if(t[t[p].s[w^1]].cnt-t[t[q].s[w^1]].cnt>0)
p=t[p].s[w^1],q=t[q].s[w^1],res+=(1<<i);
else p=t[p].s[w],q=t[q].s[w];
}
return res;
}
int sum[N];
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<=n;++i) cin>>sum[i],sum[i]=sum[i-1]^sum[i];
for(int i=1;i<=n;++i) rt[i]=++co,insert(rt[i],rt[i-1],sum[i]);
while(m--){
char opt;cin>>opt;
if(opt=='A'){
int x;cin>>x;
++n;sum[n]=sum[n-1]^x;
rt[n]=++co,insert(rt[n],rt[n-1],sum[n]);
}
else{
int l,r,x;cin>>l>>r>>x;--l,--r;
if(!l) cout<<max(sum[n]^x,ask(rt[r],rt[0],sum[n]^x))<<"\n";
else cout<<ask(rt[r],rt[l-1],sum[n]^x)<<"\n";
}
}
return 0;
}