【六个模板】简单数据结构整洁模板

区间加法线段树

洛谷 P3372

#include<bits/stdc++.h>
using namespace std;
#define md ((l+r)>>1)
#define ls (p<<1)
#define rs (p<<1|1)
#define ll long long
const int MAX = 1e5+50;
ll aa[MAX];
ll tree[MAX*4];
ll lazy[MAX*4];
void push_up(int p){
    tree[p]=tree[ls]+tree[rs];
}
void build(int p,int l,int r){
    lazy[p] = 0;
    if(l == r){
        tree[p] = aa[l];
        return;
    }
    build(ls,l,md);
    build(rs,md+1,r);
    push_up(p);
}
void add(int p,int l,int r,ll k){
    lazy[p] += k;
    tree[p] += k * (r - l + 1);
}
void push_down(int p,int l,int r){
    add(ls,l,md,lazy[p]);
    add(rs,md+1,r,lazy[p]);
    lazy[p] = 0;
}
void update(int p,int l,int r,int ux,int uy,ll k){
    if(ux <= l && uy >= r){
        add(p,l,r,k);
        return;
    }
    push_down(p,l,r);
    if(ux <= md)update(ls,l,md,ux,uy,k);
    if(uy >  md)update(rs,md+1,r,ux,uy,k);
    push_up(p);
}
ll query(int p,int l,int r,int qx,int qy){
    ll res = 0;
    if(qx <= l && r <= qy)return tree[p];
    push_down(p,l,r);
    if(qx <= md)res += query(ls,l,md,qx,qy);
    if(qy >  md)res += query(rs,md+1,r,qx,qy);
    return res;
}
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i)scanf("%lld",&aa[i]);
    build(1,1,n);
    for(int i = 1;i <= m;++i){
        ll op,t1,t2,t3;
        scanf("%lld",&op);
        if(op == 1){
            scanf("%lld%lld%lld",&t1,&t2,&t3);
            update(1,1,n,t1,t2,t3);
        }else{
            scanf("%lld%lld",&t1,&t2);
            printf("%lld\n",query(1,1,n,t1,t2));
        }
    }
    return 0;
}

区间加/乘线段树

洛谷 P3373

#include<bits/stdc++.h>
using namespace std;
#define md ((l+r)>>1)
#define ls (p<<1)
#define rs (p<<1|1)
#define ll long long
const int MAX = 1e5+50;
ll tmod;
ll aa[MAX];
ll tree[MAX*4];
ll tadd[MAX*4];
ll tmul[MAX*4];
void push_up(int p){
    tree[p]=(tree[ls]+tree[rs]) % tmod;
}
void build(int p,int l,int r){
    tadd[p] = 0;
    tmul[p] = 1;
    if(l == r){
        tree[p] = aa[l] % tmod;
        return;
    }
    build(ls,l,md);
    build(rs,md+1,r);
    push_up(p);
}
void add(int p,int l,int r,ll add,ll mul){
    tree[p] = (tree[p] * mul % tmod + add * (r - l + 1) % tmod ) % tmod;
    tmul[p] = tmul[p] * mul % tmod;
    tadd[p] = (tadd[p] * mul % tmod + add) % tmod;
}
void push_down(int p,int l,int r){
    add(ls,l,md,tadd[p],tmul[p]);
    add(rs,md+1,r,tadd[p],tmul[p]);
    tadd[p] = 0;
    tmul[p] = 1;
}
void updateMul(int p,int l,int r,int ux,int uy,ll k){
    if(ux <= l && uy >= r){
        add(p,l,r,0,k);
        return;
    }
    push_down(p,l,r);
    if(ux <= md)updateMul(ls,l,md,ux,uy,k);
    if(uy >  md)updateMul(rs,md+1,r,ux,uy,k);
    push_up(p);
}
void updateAdd(int p,int l,int r,int ux,int uy,ll k){
    if(ux <= l && uy >= r){
        add(p,l,r,k,1);
        return;
    }
    push_down(p,l,r);
    if(ux <= md)updateAdd(ls,l,md,ux,uy,k);
    if(uy >  md)updateAdd(rs,md+1,r,ux,uy,k);
    push_up(p);
}
ll query(int p,int l,int r,int qx,int qy){
    ll res = 0;
    if(qx <= l && r <= qy)return tree[p];
    push_down(p,l,r);
    if(qx <= md)res += query(ls,l,md,qx,qy);
    if(qy >  md)res += query(rs,md+1,r,qx,qy);
    res %= tmod;
    return res;
}
int main()
{
    int n,m;scanf("%d%d%lld",&n,&m,&tmod);
    for(int i = 1;i <= n;++i)scanf("%lld",&aa[i]);
    build(1,1,n);
    for(int i = 1;i <= m;++i){
        ll op,t1,t2,t3;
        scanf("%lld",&op);
        if(op == 1){
            scanf("%lld%lld%lld",&t1,&t2,&t3);
            updateMul(1,1,n,t1,t2,t3);
        }else if(op == 2){
            scanf("%lld%lld%lld",&t1,&t2,&t3);
            updateAdd(1,1,n,t1,t2,t3);
        }else{
            scanf("%lld%lld",&t1,&t2);
            printf("%lld\n",query(1,1,n,t1,t2));
        }
    }
    return 0;
}

Treap 及其相关操作

洛谷 P3369

介绍的博客

#include<bits/stdc++.h>
using namespace std;
#define md ((l+r)>>1)
#define ls (p<<1)
#define rs (p<<1|1)
#define ll long long
const int MAX = 1e5+50;
const int INF = 0x3f3f3f3f;
int na;
int ch[MAX][2];
int val[MAX],dat[MAX],siz[MAX],cnt[MAX];
int tot,root;
int New(int v){
    val[++tot] = v;
    dat[tot] = rand();
    siz[tot] = 1;
    cnt[tot] = 1;
    return tot;
}
void push_up(int id){
    siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[id];
}
void build(){
    root = New(-INF),ch[root][1] = New(INF);
    push_up(root);
}
void Rotate(int &id,int d){ // d=0 left-rotate d=1 right-rotate
    int temp = ch[id][d^1];
    ch[id][d^1] = ch[temp][d];
    ch[temp][d] = id;
    id = temp;
    push_up(ch[id][d]),push_up(id);
}
void Insert(int &id,int v){
    if(!id){
        id = New(v);
        return;
    }
    if(v == val[id])cnt[id]++;
    else{
        int d = v < val[id] ? 0 : 1;
        Insert(ch[id][d],v);
        if(dat[id] < dat[ch[id][d]])Rotate(id,d^1);
    }
    push_up(id);
}
void Remove(int &id,int v){
    if(!id)return;
    if(v == val[id]){
        if(cnt[id] > 1){
            cnt[id]--;push_up(id);
            return;
        }
        if(ch[id][0] || ch[id][1]){
            if(!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]]){
                Rotate(id,1);Remove(ch[id][1],v);
            }else{
                Rotate(id,0);Remove(ch[id][0],v);
            }
            push_up(id);
        }else{
            id = 0;
        }
        return;
    }
    v < val[id] ? Remove(ch[id][0],v) : Remove(ch[id][1],v);
    push_up(id);
}
int get_rank(int id,int v){
    if(!id)return -2;
    if(v == val[id])return siz[ch[id][0]]+1;
    if(v < val[id])return get_rank(ch[id][0],v);
    return siz[ch[id][0]] + cnt[id] + get_rank(ch[id][1],v);
}
int get_val(int id,int rk){
    if(!id)return INF;
    if(rk <= siz[ch[id][0]])return get_val(ch[id][0],rk);
    if(rk <= siz[ch[id][0]] + cnt[id])return val[id];
    return get_val(ch[id][1],rk - siz[ch[id][0]] - cnt[id]);
}
int get_pre(int v){
    int id = root,pre;
    while(id){
        if(val[id] < v)pre = val[id],id=ch[id][1];
        else id = ch[id][0];
    }
    return pre;
}
int get_nxt(int v){
    int id = root,nxt;
    while(id){
        if(val[id] > v)nxt = val[id],id = ch[id][0];
        else id = ch[id][1];
    }
    return nxt;
}
int main()
{
    build();
    scanf("%d",&na);
    for(int i = 1;i <= na;++i){
        int op,x;
        scanf("%d%d",&op,&x);
        switch(op){
        case 1:
            Insert(root,x);
            break;
        case 2:
            Remove(root,x);
            break;
        case 3:
            printf("%d\n",get_rank(root,x)-1);
            break;
        case 4:
            printf("%d\n",get_val(root,x+1));
            break;
        case 5:
            printf("%d\n",get_pre(x));
            break;
        case 6:
            printf("%d\n",get_nxt(x));
            break;
        }
    }
    return 0;
}

区间最值操作 区间最值 区间加 区间和

这个模板是别人的, 还没有自己交过题目

#include<bits/stdc++.h>
#define ll long long
#define N 500005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define inf (1<<30)
using namespace std;
inline ll read(){
    ll ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w;
}
inline void write(ll x){
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
int n,m;
ll a[N];
struct Node{int l,r;ll mx,mn,mxx,mnx,cmx,cmn;ll sum,lz;}T[N*3];
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll min(ll a,ll b){return a<b?a:b;}
inline void pushup(int p){
    T[p].sum=T[lc].sum+T[rc].sum;
    T[p].mx=max(T[lc].mx,T[rc].mx);
    T[p].cmx=(T[p].mx==T[lc].mx?T[lc].cmx:0)+(T[p].mx==T[rc].mx?T[rc].cmx:0);
    T[p].mxx=max(T[p].mx==T[lc].mx?T[lc].mxx:T[lc].mx,T[p].mx==T[rc].mx?T[rc].mxx:T[rc].mx);
    T[p].mn=min(T[lc].mn,T[rc].mn);
    T[p].cmn=(T[p].mn==T[lc].mn?T[lc].cmn:0)+(T[p].mn==T[rc].mn?T[rc].cmn:0);
    T[p].mnx=min(T[p].mn==T[lc].mn?T[lc].mnx:T[lc].mn,T[p].mn==T[rc].mn?T[rc].mnx:T[rc].mn);
}
inline void pushnow_mn(int p,ll v){
    if(T[p].mn>=v)return;
    T[p].sum+=T[p].cmn*(v-T[p].mn);
    T[p].mn=v,T[p].mx=max(T[p].mx,v);
    if(T[p].mn==T[p].mx)T[p].sum=1ll*(T[p].cmn=T[p].cmx=(T[p].r-T[p].l+1))*(T[p].mx=T[p].mn=v),T[p].mxx=-inf,T[p].mnx=inf;
    else T[p].mxx=max(T[p].mxx,v);
}
inline void pushnow_mx(int p,ll v){
    if(T[p].mx<=v)return;
    T[p].sum+=T[p].cmx*(v-T[p].mx);
    T[p].mx=v,T[p].mn=min(T[p].mn,v);
    if(T[p].mn==T[p].mx)T[p].sum=1ll*(T[p].cmn=T[p].cmx=(T[p].r-T[p].l+1))*(T[p].mx=T[p].mn=v),T[p].mxx=-inf,T[p].mnx=inf;
    else T[p].mnx=min(T[p].mnx,v);
}
inline void pushnow(int p,ll v){
    T[p].lz+=v,T[p].sum+=1ll*(T[p].r-T[p].l+1)*v;
    T[p].mn+=v,T[p].mx+=v,T[p].mxx+=v,T[p].mnx+=v;
}
inline void pushdown(int p){
    if(T[p].lz)pushnow(lc,T[p].lz),pushnow(rc,T[p].lz),T[p].lz=0;
    pushnow_mn(lc,T[p].mn),pushnow_mn(rc,T[p].mn);
    pushnow_mx(lc,T[p].mx),pushnow_mx(rc,T[p].mx);
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].lz=0;
    if(l==r){
        T[p].mx=T[p].mn=T[p].sum=a[l];
        T[p].cmx=T[p].cmn=1;
        T[p].mxx=-inf,T[p].mnx=inf;
        return;
    }
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,ll v){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr){pushnow(p,v);return;}
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline void modify1(int p,int ql,int qr,ll v){
    if(ql>T[p].r||qr<T[p].l||T[p].mn>=v)return;
    if(ql<=T[p].l&&T[p].r<=qr&&T[p].mnx>v){pushnow_mn(p,v);return;}
    pushdown(p);
    if(qr<=mid)modify1(lc,ql,qr,v);
    else if(ql>mid)modify1(rc,ql,qr,v);
    else modify1(lc,ql,mid,v),modify1(rc,mid+1,qr,v);
    pushup(p);
}
inline void modify2(int p,int ql,int qr,ll v){
    if(ql>T[p].r||qr<T[p].l||T[p].mx<=v)return;
    if(ql<=T[p].l&&T[p].r<=qr&&T[p].mxx<v){pushnow_mx(p,v);return;}
    pushdown(p);
    if(qr<=mid)modify2(lc,ql,qr,v);
    else if(ql>mid)modify2(rc,ql,qr,v);
    else modify2(lc,ql,mid,v),modify2(rc,mid+1,qr,v);
    pushup(p);
}
inline ll query_sum(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return 0;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].sum;
    pushdown(p);
    if(qr<=mid)return query_sum(lc,ql,qr);
    if(ql>mid)return query_sum(rc,ql,qr);
    return query_sum(lc,ql,mid)+query_sum(rc,mid+1,qr);
}
inline ll query_max(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return -inf;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].mx;
    pushdown(p);
    if(qr<=mid)return query_max(lc,ql,qr);
    if(ql>mid)return query_max(rc,ql,qr);
    return max(query_max(lc,ql,mid),query_max(rc,mid+1,qr));
}
inline ll query_min(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return inf;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn;
    pushdown(p);
    if(qr<=mid)return query_min(lc,ql,qr);
    if(ql>mid)return query_min(rc,ql,qr);
    return min(query_min(lc,ql,mid),query_min(rc,mid+1,qr));
}
int main(){
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();
    build(1,1,n);
    m=read();
    while(m--){
        int op=read(),l=read(),r=read();
        switch(op){
            case 1:{ll v=read();update(1,l,r,v);break;}
            case 2:{ll v=read();modify1(1,l,r,v);break;}
            case 3:{ll v=read();modify2(1,l,r,v);break;}
            case 4:{write(query_sum(1,l,r)),puts("");break;}
            case 5:{write(query_max(1,l,r)),puts("");break;}
            default:{write(query_min(1,l,r)),puts("");break;}
        }
    }
    return 0;
}

树链剖分 (路径加 路径求和 子树加 子树求和)

洛谷 P3384

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ls (p<<1)
#define rs (p<<1|1)
#define md ((l+r)>>1)
const int MAX = 1e5+50;
int MOD;

int n,m;
vector<int>V[MAX];
int dep[MAX],fa[MAX],siz[MAX],son[MAX];
void dfs1(int x,int f,int deep){
    dep[x] = deep;
    fa[x] = f;
    siz[x] = 1;
    int maxson = -1;
    for(auto it : V[x]){
        if(it == f)continue;
        dfs1(it,x,deep+1);
        siz[x] += siz[it];
        if(siz[it] > maxson){
            maxson = siz[it];
            son[x] = it;
        }
    }
}
int cnt;
int id[MAX],top[MAX];
ll aa[MAX],bb[MAX];
void dfs2(int x,int topf){
    id[x] = ++cnt;
    bb[cnt] = aa[x];
    top[x] = topf;
    if(!son[x])return;
    dfs2(son[x],topf);
    for(auto it : V[x]){
        if(it == fa[x] || it == son[x])continue;
        dfs2(it,it);
    }
}

ll tree[MAX*4],lazy[MAX*4];
void push_up(int p){
    tree[p] = (tree[ls] + tree[rs]) % MOD;
}
void build(int p,int l,int r){
    lazy[p] = 0;
    if(l == r){
        tree[p] = bb[l] % MOD;
        return;
    }
    build(ls,l,md);
    build(rs,md+1,r);
    push_up(p);
}
void add(int p,int l,int r,ll k){
    tree[p] = (tree[p] + k * (r - l + 1) % MOD) % MOD;
    lazy[p] = (lazy[p] + k) % MOD;
}
void push_down(int p,int l,int r){
    add(ls,l,md,lazy[p]);
    add(rs,md+1,r,lazy[p]);
    lazy[p] = 0;
}
void update(int p,int l,int r,int ux,int uy,ll k){
    if(ux <= l && uy >= r){
        add(p,l,r,k);
        return;
    }
    push_down(p,l,r);
    if(md >= ux)update(ls,l,md,ux,uy,k);
    if(md <  uy)update(rs,md+1,r,ux,uy,k);
    push_up(p);
}
ll query(int p,int l,int r,int qx,int qy){
    if(qx <= l && qy >= r){
        return tree[p] % MOD;
    }
    push_down(p,l,r);
    ll res = 0;
    if(md >= qx)res = (res + query(ls,l,md,qx,qy)) % MOD;
    if(md <  qy)res = (res + query(rs,md+1,r,qx,qy)) % MOD;
    return res;
}


int qRange(int x,int y){
    ll ans = 0;
    while(top[x] != top[y]){
        if(dep[top[x]] < dep[top[y]])swap(x,y);
        ans = (ans + query(1,1,n,id[top[x]],id[x])) % MOD;
        x = fa[top[x]];
    }
    if(dep[x] > dep[y])swap(x,y);
    ans = (query(1,1,n,id[x],id[y]) + ans) % MOD;
    return ans;
}
int qSon(int x){
    return query(1,1,n,id[x],id[x] + siz[x] - 1);
}
void uRange(int x,int y,int k){
    k %= MOD;
    while(top[x] != top[y]){
        if(dep[top[x]] < dep[top[y]])swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x = fa[top[x]];
    }
    if(dep[x] > dep[y])swap(x,y);
    update(1,1,n,id[x],id[y],k);
}
void uSon(int x,int k){
    update(1,1,n,id[x],id[x]+siz[x]-1,k);
}
int main(){
    int root;
    scanf("%d%d%d%d",&n,&m,&root,&MOD);
    for(int i = 1;i <= n;++i){
        scanf("%lld",&aa[i]);
    }
    for(int i = 1;i < n;++i){
        int ta,tb;scanf("%d%d",&ta,&tb);
        V[ta].push_back(tb);
        V[tb].push_back(ta);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,1,n);
    while(m--){
        int op,x,y,z;
        scanf("%d",&op);
        if(op == 1){
            scanf("%d%d%d",&x,&y,&z);
            uRange(x,y,z);
        }else if(op == 2){
            scanf("%d%d",&x,&y);
            printf("%lld\n",qRange(x,y));
        }else if(op == 3){
            scanf("%d%d",&x,&y);
            uSon(x,y);
        }else{
            scanf("%d",&x);
            printf("%lld\n",qSon(x));
        }
    }
    return 0;
}

Rope 实现区间翻转

洛谷 P3391

#include <bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define ll long long
const int MAX = 1e5+50;
rope<int>str,rstr;
int n,m;
void rev(int st,int ed){
    ed++;
    rope<int>tmp = str.substr(st+str.begin(),ed+str.begin());
    str = str.substr(str.begin(), st + str.begin()) + rstr.substr(n - ed + rstr.begin(), n - st + rstr.begin()) + str.substr(ed + str.begin(), str.length() + str.begin());
    rstr = rstr.substr(rstr.begin(), n - ed + rstr.begin()) + tmp + rstr.substr(n - st + rstr.begin(), rstr.length() + rstr.begin());
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i){
        str.append(i);
        rstr.append(n-i+1);
    }
    for(int i = 1;i <= m;++i){
        int s,t;scanf("%d%d",&s,&t);
        rev(s-1,t-1);
    }
    for(int i = 0;i < n;++i){
        printf("%d ",str[i]);
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值