線段樹の模板
阿新 • • 發佈:2021-07-13
0x01 線段樹
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int M=1e6; char buf[1<<21],*p1=buf,*p2=buf; ll n,m,q; ll sum[M<<2],add[M<<2]; char sr[1<<21],z[20]; int C=-1,Z; ll read(){ ll x=0,y=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') y=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } return x*y; } inline void Ot(){ fwrite(sr,1,C+1,stdout),C=-1; } inline void print(ll x){ if(C>1<<20) Ot(); if(x<0) sr[++C]=45,x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z); sr[++C]='\n'; } inline void build(){ for(m=1;m<=n;m<<=1); for(int i=m+1;i<=m+n;++i) sum[i]=read(); for(int i=m-1;i;--i) sum[i]=sum[i<<1]+sum[i<<1|1]; } inline void update_part(int s,int t,ll v){ ll A=0,lc=0,rc=0,len=1; for(s+=m-1,t+=m+1;s^t^1;s>>=1,t>>=1,len<<=1){ if(s&1^1) add[s^1]+=v,lc+=len; if(t&1) add[t^1]+=v,rc+=len; sum[s>>1]+=v*lc,sum[t>>1]+=v*rc; } for(lc+=rc,s>>=1;s;s>>=1) sum[s]+=v*lc; } inline ll query_sum(int s,int t){ ll lc=0,rc=0,len=1,ans=0; for(s+=m-1,t+=m+1;s^t^1;s>>=1,t>>=1,len<<=1){ if(s&1^1) ans+=sum[s^1]+len*add[s^1],lc+=len; if(t&1) ans+=sum[t^1]+len*add[t^1],rc+=len; if(add[s>>1]) ans+=add[s>>1]*lc; if(add[t>>1]) ans+=add[t>>1]*rc; } for(lc+=rc,s>>=1;s;s>>=1) if(add[s]) ans+=add[s]*lc; return ans; } int main(){ n=read(),q=read(),build(); int opt,x,y; ll k; while(q--){ opt=read(),x=read(),y=read(); if(opt&1) k=read(),update_part(x,y,k); else print(query_sum(x,y)); } Ot(); return 0; }
這也是\(P3372\)的std
0x02 普通平衡樹
#include<bits/stdc++.h> typedef long long ll; typedef unsigned long long ull; using namespace std; const int MAXN=1E5+10; struct node{ int son[2],fa,v,siz,tms; }t[MAXN]; int Rt,cnt,n; #define ls(x) t[x].son[0] #define rs(x) t[x].son[1] #define fa(x) t[x].fa #define rson(x) (rs(fa(x))==x) int nd(int val){ ++cnt; t[cnt].v=val;t[cnt].siz=t[cnt].tms=1; return cnt; } void pushup(int x){ t[x].siz=t[ls(x)].siz+t[rs(x)].siz+t[x].tms; } void rotate(int x){ int y=fa(x),z=fa(y); bool rsx=rson(x),rsy=rson(y); if(z) t[z].son[rsy]=x; else Rt=x; t[y].son[rsx]=t[x].son[!rsx]; t[x].son[!rsx]=y; fa(t[y].son[rsx])=y;fa(y)=x;fa(x)=z; pushup(y); } void splay(int x){ while(fa(x)){ if(fa(fa(x))) rotate(rson(x)^rson(fa(x))?x:fa(x)); rotate(x); } pushup(x); } int find(int x,int val){ if(t[x].v==val) return x; if(t[x].v<val) return rs(x)?find(rs(x),val):x; else return ls(x)?find(ls(x),val):x; } int Pred(int x){ splay(x); x=ls(x); while(rs(x)) x=rs(x); return x; } int Succ(int x){ splay(x); x=rs(x); while(ls(x)) x=ls(x); return x; } void insert(int val){ if(!Rt) return Rt=nd(val),void(); int x=find(Rt,val); if(t[x].v==val) return splay(x),++t[x].tms,++t[x].siz,void(); int z=nd(val); t[x].son[val>t[x].v]=z; fa(z)=x; while(x) pushup(x),x=fa(x); splay(z); } void erase(int val){ int x=find(Rt,val); if(t[x].tms>1) return splay(x),--t[x].tms,--t[x].siz,void(); splay(x); if(rs(x)){ int y=Succ(x); fa(rs(x))=0; splay(y);Rt=y; ls(Rt)=ls(x); fa(ls(Rt))=Rt; pushup(Rt); } else{ fa(ls(x))=0; Rt=ls(x); } } int Rank(int val){ int x=find(Rt,val); if(t[x].v<val) x=Succ(x); splay(x); return t[ls(x)].siz+1; } int kth(int x,int k){ if(t[ls(x)].siz+1<=k&&k<=t[ls(x)].siz+t[x].tms) return t[x].v; if(t[ls(x)].siz+t[x].tms>k) return kth(ls(x),k); else return kth(rs(x),k-t[x].tms-t[ls(x)].siz); } int Pred_val(int val){ int x=find(Rt,val); if(t[x].v<val) return t[x].v; return t[Pred(x)].v; } int Succ_val(int val){ int x=find(Rt,val); if(t[x].v>val) return t[x].v; return t[Succ(x)].v; } signed main(){ scanf("%d",&n); for(int i=1,opt,x;i<=n;i++){ scanf("%d%d",&opt,&x); if(opt==1) insert(x); else if(opt==2) erase(x); else if(opt==3) printf("%d\n",Rank(x)); else if(opt==4) printf("%d\n",kth(Rt,x)); else if(opt==5) printf("%d\n",Pred_val(x)); else if(opt==6) printf("%d\n",Succ_val(x)); } }
這也是 \(P3369\) 的正解
0x03 文藝平衡樹
#include<bits/stdc++.h> #define Ls(x) tree[x].son[0] #define Rs(x) tree[x].son[1] #define rson(x) (tree[tree[x].fa].son[1]==x) using namespace std; typedef long long ll; typedef unsigned long long ull; const int MAXN=100010; struct node{ int son[2],val,siz,fa; bool rev; }tree[MAXN]; int root,cnt; int n,q,L,R; inline void pushup(const int &x){ tree[x].siz=tree[Ls(x)].siz+tree[Rs(x)].siz+1; tree[Ls(x)].fa=x;tree[Rs(x)].fa=x; } inline void pushdown(const int &x){ if(tree[x].rev){ swap(Ls(x),Rs(x)); tree[Ls(x)].rev^=1; tree[Rs(x)].rev^=1; tree[x].rev=0; } } void rotate(int x){ int fx=tree[x].fa,ffx=tree[fx].fa; bool rsx=rson(x),rsfx=rson(fx); if(ffx) tree[ffx].son[rsfx]=x; else root=x; tree[x].fa=ffx;tree[fx].fa=x; tree[fx].son[rsx]=tree[x].son[rsx^1]; tree[x].son[rsx^1]=fx; pushup(fx); pushup(x); } stack<int> stk; void splay(int x,int pos){ stk.push(x); for(int i=x;tree[i].fa!=pos;i=tree[i].fa) stk.push(tree[i].fa); while(!stk.empty()) pushdown(stk.top()),stk.pop(); while(tree[x].fa!=pos){ int fx=tree[x].fa,ffx=tree[fx].fa; if(ffx!=pos) rotate(rson(x)^rson(fx)?x:fx); rotate(x); } } int find(int x,int pos){ pushdown(x); if(pos==tree[Ls(x)].siz+1) return x; if(tree[Ls(x)].siz+1<pos) return find(Rs(x),pos-tree[Ls(x)].siz-1); else return find(Ls(x),pos); } void rev(int l,int r){ int _l=find(root,l),_r=find(root,r+2); splay(_l,0),splay(_r,_l); tree[tree[_r].son[0]].rev^=1; } void print(int x){ pushdown(x); if(Ls(x)) print(Ls(x)); if(x>=2&&x<n+2) printf("%d ",x-1); if(Rs(x)) print(Rs(x)); } signed main(){ scanf("%d%d",&n,&q); root=1; for(int i=1;i<=n+2;i++){ tree[i].fa=i-1,tree[i].siz=n+3-i; if(i!=n+2) tree[i].son[1]=i+1; } tree[root].fa=0; for(int i=1;i<=q;i++){ scanf("%d%d",&L,&R); rev(L,R); } print(root); puts(""); }
這也是 \(P3391\) 的正解
0x04 LCA
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
typedef long long ll;
const int N=501000;
int a,b,n,m,s,k=0;
int head[N],d[N],p[N][21];
struct node{
int v,next;
}e[N<<1];
inline ll read(){
ll x=0,y=1;
char c=getchar();
while (c<'0'||c>'9'){
if(c=='-')
y=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*y;
}
void add(int n,int v){
e[k].v=v;
e[k].next=head[n];
head[n]=k++;
}
void dfs(int u,int fa){
d[u]=d[fa]+1;
p[u][0]=fa;
for(register int i=1;(1<<i)<=d[u];i++)
p[u][i]=p[p[u][i-1]][i-1];
for(register int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v!=fa)
dfs(v,u);
}
}
int lca(int a,int b){
if(d[a]>d[b])
swap(a,b);
for(register int i=20;i>=0;i--)
if(d[a]<=d[b]-(1<<i))
b=p[b][i];
if(a==b)
return a;
for(register int i=20;i>=0;i--){
if(p[a][i]==p[b][i])
continue;
else
a=p[a][i],b=p[b][i];
}
return p[a][0];
}
int main(){
memset(head,-1,sizeof(head));
n=read(),m=read(),s=read();
for(register int i=1;i<=n-1;i++){
register int x=read(),y=read();
add(x,y);
add(y,x);
}
dfs(s,0);
for(register int i=1;i<=m;i++){
a=read();
b=read();
printf("%d\n",lca(a,b));
}
return 0;
}
這也是 \(P3379\) 的正解