线段树の模板

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\) 的正解

上一篇:【洛谷P5043】【模板】树同构


下一篇:TC15279 SpanningSubgraphs