树剖
戳他
平衡树
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; |
| |
| 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]; |
| } |
| |
| 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){ |
| |
| 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; |
| |
| |
| |
| change(1,1,co,y,y1,a[i].val); |
| ans+=tr[1]*(a[i+1].x-a[i].x); |
| |
| } |
| 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; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步