板子

· · 个人记录

线段树

#include <bits/stdc++.h>
using namespace std;
const  long long MX=1e5+10;
long long n,m,cnt=0;
long long input[MX]={0};
struct Node{
    long long lazy,sum;
    long long lc,rc;
}tree[MX<<1];
inline void addnode(long long &now,long long l,long long r,long long val){
    if(now==0)  now=++cnt;
    tree[now].sum+=(r-l+1)*val;tree[now].lazy+=val;return ;
}

inline void pushup(long long now){
    tree[now].sum=tree[tree[now].lc].sum+tree[tree[now].rc].sum;return ;
}
inline void pushdown(long long now,long long l,long long r){
    if(l>=r)  return;
    long long mid=(l+r-1)>>1;
    addnode(tree[now].lc,l,mid,tree[now].lazy);
    addnode(tree[now].rc,mid+1,r,tree[now].lazy);
    tree[now].lazy=0;
    return ;
}
void update(long long now,long long lt,long long rt,long long l,long long r,long long val){
    if(r<lt||l>rt){
        return ;
    }
    if(l<=lt&&rt<=r){
        addnode(now,lt,rt,val);
        return ;
    }
    pushdown(now,lt,rt);
    long long mid=(lt+rt-1)/2;
    update(tree[now].lc,lt,mid,l,r,val);update(tree[now].rc,mid+1,rt,l,r,val);
    pushup(now);
    return ;
}
long long query(long long now,long long lt,long long rt,long long l,long long r){
    if(r<lt||l>rt){
        return 0;
    }
    if(l<=lt&&rt<=r){
        return tree[now].sum;
    }
    pushdown(now,lt,rt);
    long long mid=(lt+rt-1)/2;
    return query(tree[now].lc,lt,mid,l,r)+query(tree[now].rc,mid+1,rt,l,r);
}
//======================================
int main()
{
    scanf("%lld%lld",&n,&m);
    long long root = 1; //根结点编号
    cnt = 1; //总结点数量 
    for(long long i = 1; i <= n; i++)
    {
        long long x;
        scanf("%lld",&x);
        update(root, 1, n, i, i, x);
    }

    for(long long i = 1; i <= m; i++)
    {
        long long op, x, y, val;
        scanf("%lld%lld%lld",&op,&x,&y);
        if(op == 1)
        {
            scanf("%lld",&val);
            update(root, 1, n, x, y, val); 
        }
        else{
            printf("%lld\n",query(root,1,n,x,y));
        }
    }
    return 0;
}

平衡树

FHQ

const int MX=1e5+10;
struct Node{
    int l,r;
    int val,key;
    int size;
}fhq[MX];
int cnt,root;
inline int newnode(int val){
    fhq[++cnt].val=val;
    fhq[cnt].key=rand();
    fhq[cnt].size=1;
    return cnt;
}
inline void update(int now){
    fhq[now].size=fhq[fhq[now].l].size+fhq[fhq[now].r].size+1;
}
void split(int now,int val,int &x,int &y){
    if(!now) x=y=0;
    else{
        if(fhq[now].val<=val){
            x=now;
            split(fhq[now].r,val,fhq[now].r,y);
        }
        else{
            y=now;
            split(fhq[now].l,val,x,fhq[now].l);
        }
        update(now);    //此处update位置不能写在下面,会合并根节点
    }
}

int merge(int x,int y){
    if(!x||!y)  return x+y;
    else{
        if(fhq[x].key<=fhq[y].key){
            fhq[x].r=merge(fhq[x].r,y);
            update(x);
            return x;
        }
        else{
            fhq[y].l=merge(x,fhq[y].l);
            update(y);
            return y;
        }
    }
}
int x,y,z;
inline void ins(int val){         //插入x数
    split(root,val,x,y);
    root=merge(merge(x,newnode(val)),y);
}
inline void del(int val){         //删除x数(若有多个相同的数,应只删除一个)
    split(root,val,x,z);
    split(x,val-1,x,y);
    y=merge(fhq[y].l,fhq[y].r);
    root=merge(merge(x,y),z);
}
inline int getrank(int val){      //查询x数的排名(排名定义为比当前数小的数的个数+1)
    split(root,val-1,x,y);
    int re=fhq[x].size+1;
    root=merge(x,y);
    return re;
}
inline int getnum(int rank){      //查询排名为x的数
    int now=root;
    while(now){
        if(fhq[fhq[now].l].size+1==rank)  break;
        else if(fhq[fhq[now].l].size>=rank){
            now=fhq[now].l;
        }
        else{
            rank-=fhq[fhq[now].l].size+1;
            now=fhq[now].r;
        }
    }
    return fhq[now].val;
}
inline int pre(int val){          //求x的前驱(前驱定义为小于x,且最大的数)
    split(root,val-1,x,y);
    int now=x;
    while(fhq[now].r)  now=fhq[now].r;
    int re=fhq[now].val;
    root=merge(x,y);
    return re;
}
inline int nxt(int val){          //求x的后继(后继定义为大于x,且最小的数)
    split(root,val,x,y);
    int now=y;
    while(fhq[now].l)  now=fhq[now].l;
    int re=fhq[now].val;
    root=merge(x,y);
    return re;
}

二逼平衡树

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 10, MAXM = 1e7;
const int INF = 0x7fffffff;

int input[MAXN] = {0};
int n, m;
struct Node
{
    int l, r;
    int key, val;
    int size;
} fhq[MAXM];
int cnt;
struct FHQ_Treap
{
    int root = 0;
    inline int newnode(int val)
    {
        fhq[++cnt].val = val;
        fhq[cnt].size = 1;
        fhq[cnt].key = (rand() << 10) + rand();
        return cnt;
    }
    inline void update(int now)
    {
        fhq[now].size = fhq[fhq[now].l].size + fhq[fhq[now].r].size + 1;
    }
    void split(int now, int val, int &x, int &y)
    {
        if (!now)
            x = y = 0;
        else
        {
            if (fhq[now].val <= val)
            {
                x = now;
                split(fhq[now].r, val, fhq[now].r, y);
            }
            else
            {
                y = now;
                split(fhq[now].l, val, x, fhq[now].l);
            }
            update(now);
        }
    }
    int merge(int x, int y)
    {
        if (!x || !y)
            return x + y;
        else
        {
            if (fhq[x].key <= fhq[y].key)
            {
                fhq[x].r = merge(fhq[x].r, y);
                update(x);
                return x;
            }
            else
            {
                fhq[y].l = merge(x, fhq[y].l);
                update(y);
                return y;
            }
        }
    }
    int x, y, z;
    inline void Insert(int val)
    {
        split(root, val, x, y);
        root = merge(merge(x, newnode(val)), y);
    }
    inline void Delete(int val)
    {
        split(root, val, x, z);
        split(x, val - 1, x, y);
        y = merge(fhq[y].l, fhq[y].r);
        root = merge(merge(x, y), z);
    }
    inline void Build(int l, int r)
    {
        for (int i = l; i <= r; i++)
            Insert(input[i]);
    }
    inline int FindRank(int val)
    { // 查询x数的排名(排名定义为比当前数小的数的个数+1)
        split(root, val - 1, x, y);
        int re = fhq[x].size + 1;
        root = merge(x, y);
        return re;
    }
    inline int getnum(int rank)
    { // 查询排名为x的数
        int now = root;
        while (now)
        {
            if (fhq[fhq[now].l].size + 1 == rank)
                break;
            else if (fhq[fhq[now].l].size >= rank)
            {
                now = fhq[now].l;
            }
            else
            {
                rank -= fhq[fhq[now].l].size + 1;
                now = fhq[now].r;
            }
        }
        return fhq[now].val;
    }
    inline int Lower(int val)
    { // 求x的前驱(前驱定义为小于x,且最大的数)
        split(root, val - 1, x, y);
        int ans;
        if (fhq[x].size)
        {
            int now = x;
            while (fhq[now].r)
            {
                now = fhq[now].r;
            }
            ans = fhq[now].val;
        }
        else
            ans = -INF;
        root = merge(x, y);
        return ans;
    }
    inline int Upper(int val)
    { // 求x的后继(后继定义为大于x,且最小的数)
        split(root, val, x, y);
        int ans;
        if (fhq[y].size)
        {
            int now = y;
            while (fhq[now].l)
            {
                now = fhq[now].l;
            }
            ans = fhq[now].val;
        }
        else
            ans = INF;
        root = merge(x, y);
        return ans;
    }
} FT[MAXN << 2];
#define mid ((x + y) >> 1)
#define lson (pst << 1)
#define rson (pst << 1 | 1)

struct SegmentTree
{
    int root[MAXN << 2];

    inline void Build(int x, int y, int pst)
    {
        FT[pst].Build(x, y);
        if (x != y)
            Build(x, mid, lson), Build(mid + 1, y, rson);

        return;
    }

    inline int QueryRank(int x, int y, int pst, int l, int r, int key)
    {
        if (y < l || x > r)
            return 0;
        if (l <= x && y <= r)
            return FT[pst].FindRank(key) - 1;

        return QueryRank(x, mid, lson, l, r, key) + QueryRank(mid + 1, y, rson, l, r, key);
    }

    inline int QueryKey(int l, int r, int rak)
    {
        int x = 0, y = 1e8, ans = -1;
        while (x <= y)
        {
            if (QueryRank(1, n, 1, l, r, mid) + 1 <= rak)
                ans = mid, x = mid + 1;
            else
                y = mid - 1;
        }

        return ans;
    }

    inline void Update(int x, int y, int pst, int p, int k)
    {
        FT[pst].Delete(input[p]);
        FT[pst].Insert(k);

        if (x != y)
        {
            if (p <= mid)
                Update(x, mid, lson, p, k);
            else
                Update(mid + 1, y, rson, p, k);
        }

        return;
    }

    inline int Lower(int x, int y, int pst, int l, int r, int k)
    {
        if (y < l || x > r)
            return -INF;
        if (l <= x && y <= r)
            return FT[pst].Lower(k);
        return max(Lower(x, mid, lson, l, r, k), Lower(mid + 1, y, rson, l, r, k));
    }

    inline int Upper(int x, int y, int pst, int l, int r, int k)
    {
        if (y < l || x > r)
            return INF;
        if (l <= x && y <= r)
            return FT[pst].Upper(k);
        return min(Upper(x, mid, lson, l, r, k), Upper(mid + 1, y, rson, l, r, k));
    }

} ST;

signed main(void)
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", input + i);

    ST.Build(1, n, 1);

    for (int i = 1, opt, l, r, p, k; i <= m; i++)
    {
        scanf("%d", &opt);

        if (opt == 1)
        {
            scanf("%d %d %d", &l, &r, &k);
            printf("%d\n", ST.QueryRank(1, n, 1, l, r, k) + 1);
        }

        if (opt == 2)
        {
            scanf("%d %d %d", &l, &r, &k);
            printf("%d\n", ST.QueryKey(l, r, k));
        }

        if (opt == 3)
        {
            scanf("%d %d", &p, &k);
            ST.Update(1, n, 1, p, k);
            input[p] = k;
        }

        if (opt == 4)
        {
            scanf("%d %d %d", &l, &r, &k);
            printf("%d\n", ST.Lower(1, n, 1, l, r, k));
        }

        if (opt == 5)
        {
            scanf("%d %d %d", &l, &r, &k);
            printf("%d\n", ST.Upper(1, n, 1, l, r, k));
        }
    }
    return 0;
}

重链剖分/树链剖分

#include<bits/stdc++.h>
using namespace std;const int MX=1e5+10;
int n,m,r,p;int input[MX]={0};int siz[MX]={0};int fath[MX]={0};int top[MX]={0};int dfn[MX]={0};int son[MX]={0};int high[MX]={0};int w[MX]={0};
//线段树好闪,拜谢线段树
struct node{
    long long sum;
    long long lc,rc;
    long long lazy;
}tree[MX<<1];
long long cnt=1,root=1;
inline void update(long long now){
    tree[now].sum=tree[tree[now].lc].sum+tree[tree[now].rc].sum;
}
inline void addnode(long long &now,long long l,long long r,long long val){
    if(now==0)  now=++cnt;
    tree[now].sum+=((r-l+1)*val)%p;tree[now].sum%=p;
    tree[now].lazy+=val%p;tree[now].lazy%=p;
}
inline void pushdown(long long now,long long l,long long r){
    if(l>=r)  return;
    long long mid=(r+l-1)>>1;
    addnode(tree[now].lc,l,mid,tree[now].lazy);
    addnode(tree[now].rc,mid+1,r,tree[now].lazy);
    tree[now].lazy=0;
}
void add(long long now,long long lt,long long rt,long long l,long long r,long long val){
    if(lt>r||l>rt)  return;
    if(l<=lt&&rt<=r){
        addnode(now,lt,rt,val);
        return ;
    }
    long long mid=(rt+lt-1)>>1;pushdown(now,lt,rt);
    add(tree[now].lc,lt,mid,l,r,val);add(tree[now].rc,mid+1,rt,l,r,val);
    update(now);
    return ;
}
long long cy(long long now,long long lt,long long rt,long long l,long long r){
    if(lt>r||l>rt)  return 0;
    if(l<=lt&&rt<=r){
        return tree[now].sum;
    }
    long long mid=(rt+lt-1)>>1;pushdown(now,lt,rt);
    return (cy(tree[now].lc,lt,mid,l,r)+cy(tree[now].rc,mid+1,rt,l,r))%p;
}
void build_t(){
    for(int i=1;i<=n;i++){
        add(root,1,n,i,i,w[i]);
    }
}
/*
int siz[MX]={0};    大小
int fa[MX]={0};     父亲
int top[MX]={0};    重链开始的地方
int dfn[MX]={0};    DFS序
int son[MX]={0};   重儿子
int high[MX]={0};  高度
int w[MX]={0};     时间戳权值
*/
vector<int> vec[MX];
void dfs1(int now,int fa){//确定  大小,父亲,高度,重儿子
    siz[now]=1;fath[now]=fa;high[now]=high[fa]+1;
    int maxn=-0x3f3f3f3f;
    for(auto to:vec[now]){
        if(to==fa)  continue;
        dfs1(to,now);
        siz[now]+=siz[to];
        if(maxn<siz[to]){
            maxn=siz[to];
            son[now]=to;
        }
    }
}
int tim=0;
void dfs2(int now,int fa){//确定重链开头,时间戳,dfs序
    dfn[now]=++tim;
    top[now]=fa;
    w[tim]=input[now];
    if(!son[now])  return ;
    dfs2(son[now],fa);
    for(auto to:vec[now]){
        if(to==fath[now]||to==son[now])  continue;
        dfs2(to,to);
    }
}

int main(){
    scanf("%d%d%d%d",&n,&m,&r,&p);
    for(int i=1;i<=n;i++){
        scanf("%d",&input[i]);
    }
    for(int i=1;i<n;i++){
        int x,y;scanf("%d%d",&x,&y);
        vec[x].push_back(y);vec[y].push_back(x);
    }
    dfs1(r,r);
    dfs2(r,r);
    build_t();
    for(int i=1;i<=m;i++){
        int op;scanf("%d",&op);
        if(op==1){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            z%=p;
            while(top[x]!=top[y]){
                if(high[top[x]]<high[top[y]]){
                    swap(x,y);
                }
                add(root,1,n,dfn[top[x]],dfn[x],z);
                x=fath[top[x]];
            }
            if(high[x]>high[y])  swap(x,y);
            add(root,1,n,dfn[x],dfn[y],z);
        }
        else if(op==2){
            int x,y;
            scanf("%d%d",&x,&y);
            int sum=0;
            while(top[x]!=top[y]){
                if(high[top[x]]<high[top[y]])  swap(x,y);
                sum=(sum+cy(root,1,n,dfn[top[x]],dfn[x]))%p;
                x=fath[top[x]];
            }
            if(high[x]>high[y])  swap(x,y);
            sum=(sum+cy(root,1,n,dfn[x],dfn[y]))%p;
            printf("%d\n",sum%p);
        }
        else if(op==3){
            int x,z;
            scanf("%d%d",&x,&z);
            add(root,1,n,dfn[x],dfn[x]+siz[x]-1,z);
        }
        else{
            int x;
            scanf("%d",&x);
            printf("%d\n",cy(root,1,n,dfn[x],dfn[x]+siz[x]-1));
        }
    }

    return 0;
}