模板集合

· · 个人记录

目标

字符串

前缀函数与 KMP 算法

P3375 【模板】KMP

#include<bits/stdc++.h>
#define int long long
using namespace std;
string a,b;
int n,m;
int nxt[1111111];
signed main()
{
    cin>>a>>b;
    n=a.size(),m=b.size();
    a=" "+a;
    b=" "+b;
    nxt[1]=0;
    for(int i=2,j=0;i<=m;i++)
    {
        while(j and b[i]!=b[j+1])
        {
            j=nxt[j];
        }
        if(b[i]==b[j+1])
        {
            j++;
        }
        nxt[i]=j;
    }
    for(int i=1,j=0;i<=n;i++)
    {
        while(j and a[i]!=b[j+1])
        {
            j=nxt[j];
        }
        if(a[i]==b[j+1])
        {
            j++;
        }
        if(j==m)
        {
            cout<<i-j+1<<endl;
        }
    }
    for(int i=1;i<=m;i++)
    {
        cout<<nxt[i]<<" ";
    }
}

数据结构

线段树

P3372 【模板】线段树 1

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
int a[111111];
struct node
{
    int l, r, s, lz;
} tr[444444];
void updata(int root)
{
    tr[root].l = tr[root * 2].l;
    tr[root].r = tr[root * 2 + 1].r;
    tr[root].s = tr[root * 2].s + tr[root * 2 + 1].s;
}
void pushdown(int root)
{
    tr[root * 2].lz += tr[root].lz;
    tr[root * 2 + 1].lz += tr[root].lz;
    tr[root * 2].s += tr[root].lz * (tr[root * 2].r - tr[root * 2].l + 1);
    tr[root * 2 + 1].s += tr[root].lz * (tr[root * 2 + 1].r - tr[root * 2 + 1].l + 1);
    tr[root].lz = 0;
}
void build(int root, int l, int r)
{
    if (l == r)
    {
        tr[root].l = l;
        tr[root].r = r;
        tr[root].s = a[l];
        return;
    }
    int mid = (l + r) / 2;
    build(root * 2, l, mid);
    build(root * 2 + 1, mid + 1, r);
    updata(root);
}
int search(int root, int l, int r)
{
    if (l == tr[root].l and r == tr[root].r)
    {
        return tr[root].s;
    }
    int s = 0;
    if (tr[root].lz != 0)
    {
        pushdown(root);
    }
    if (r <= tr[root * 2].r)
    {
        s += search(root * 2, l, r);
    }
    else if (l >= tr[root * 2 + 1].l)
    {
        s += search(root * 2 + 1, l, r);
    }
    else
    {
        s += search(root * 2, l, tr[root * 2].r) + search(root * 2 + 1, tr[root * 2 + 1].l, r);
    }
    return s;
}
void change2(int root, int l, int r, int x)
{
    if (l <= tr[root].l and r >= tr[root].r)
    {
        tr[root].lz += x;
        tr[root].s += x * (tr[root].r - tr[root].l + 1);
        return;
    }
    if (tr[root].lz != 0)
    {
        pushdown(root);
    }
    if (r <= tr[root * 2].r)
    {
        change2(root * 2, l, r, x);
    }
    else if (l >= tr[root * 2 + 1].l)
    {
        change2(root * 2 + 1, l, r, x);
    }
    else
    {
        change2(root * 2, l, tr[root * 2].r, x);
        change2(root * 2 + 1, tr[root * 2 + 1].l, r, x);
    }
    updata(root);
}
signed main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    build(1, 1, n);
    for (int i = 1, op, x, y, z; i <= m; i++)
    {
        cin >> op;
        if (op == 1)
        {
            cin >> x >> y >> z;
            change2(1, x, y, z);
        }
        else
        {
            cin >> x >> y;
            cout << search(1, x, y) << endl;
        }
    }
}

二叉搜索树 & 平衡树

P3369 【模板】普通平衡树

旋转 treap

#include<bits/stdc++.h>
#define int long long
using namespace std;
char buf[1 << 20], *p1, *p2;
#define gc()                                                               \
  (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) \
       ? EOF                                                               \
       : *p1++)
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
inline void print(int x)
{
    if (x<0)
    {
        putchar('-');x=-x;
    }
    if (x>9) print(x/10);
    putchar(x%10+'0');
}
const int M=100000000;
struct node{
    int l,r,val,sz,w,cnt;
}tr[222222];
void change(int root)
{
    if(root)
    {
        tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+tr[root].cnt;
    }
}
void zig(int &root)
{
    int tx=tr[root].l;
    tr[root].l=tr[tx].r;
    tr[tx].r=root;
    change(root);
    change(tx);
    root=tx;
}
void zag(int &root)
{
    int tx=tr[root].r;
    tr[root].r=tr[tx].l;
    tr[tx].l=root;
    change(root);
    change(tx);
    root=tx;
}
void tupdate(int &root)
{
    if(tr[root].w<tr[tr[root].l].w)
    {
        zig(root);
    }
    else if(tr[root].w<tr[tr[root].r].w)
    {
        zag(root);
    }
    change(root);
}
int c;
void tinsert(int &root,int x)
{
    if(!root)
    {
        root=++c;
        tr[root].val=x;
        tr[root].cnt++;
        tr[root].sz++;
        tr[root].w=rand()%M;
        return;
    }
    if(x<tr[root].val)
    {
        tinsert(tr[root].l,x);
    }
    else if(x>tr[root].val)
    {
        tinsert(tr[root].r,x);
    }
    else if(x==tr[root].val)
    {
        tr[root].cnt++;
        tr[root].sz++;
    }
    if(root)
    {
        tupdate(root);
    }
}
void tdelete(int &root,int x)
{
    if(tr[root].val==x)
    {
        if(tr[root].cnt>1)
        {
            tr[root].cnt--;
            tr[root].sz--;
        }
        else
        {
            if(!tr[root].l or !tr[root].r)
            {
                root=tr[root].l+tr[root].r;
            }
            else
            {
                if(tr[tr[root].l].w<tr[root].w)
                {
                    zig(root);
                }
                else
                {
                    zag(root);
                }
                tdelete(root,x);
            }
        }
    }
    else if(x<tr[root].val)
    {
        tdelete(tr[root].l,x);
    }
    else if(x>tr[root].val)
    {
        tdelete(tr[root].r,x);
    }
    change(root);
}
int root;
bool tfind(int x)
{
    int rt=root;
    while(rt!=0 and tr[rt].val!=x)
    {
        if(x<tr[rt].val)
        {
            rt=tr[rt].l;
        }
        else
        {
            rt=tr[rt].r;
        }
    }
    return rt;
}
int tx_min(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x<=tr[rt].val)
        {
            rt=tr[rt].l;
        }
        else
        {
            ans+=tr[tr[rt].l].sz+tr[rt].cnt;
            rt=tr[rt].r;
        }
    }
    return ans;
}
int tx_rank(int x)
{
    int rt=root;
    while(rt!=0)
    {
        if(tr[tr[rt].l].sz<x)
        {
            if(tr[tr[rt].l].sz+tr[rt].cnt>=x)
            {
                return rt;
            }
            else
            {
                x-=(tr[tr[rt].l].sz+tr[rt].cnt);
                rt=tr[rt].r;
            }
        }
        else
        {
            rt=tr[rt].l;
        }
    }
    return 0;
}
int tx_q(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x>tr[rt].val)
        {
            ans=rt;
            rt=tr[rt].r;
        }
        else
        {
            rt=tr[rt].l;
        }
    }
    return ans;
}
int tx_h(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x<tr[rt].val)
        {
            ans=rt;
            rt=tr[rt].l;
        }
        else
        {
            rt=tr[rt].r;
        }
    }
    return ans;
}
int n;
signed main()
{
    srand(time(0));
    // cin>>n;
    n=read();
    for(int i=1,op,x;i<=n;i++)
    {
        // cin>>op>>x;
        op=read();
        x=read();
        if(op==1)
        {
            tinsert(root,x);
        }
        else if(op==2)
        {
            if(!tfind(x))
            {
                continue;
            }
            tdelete(root,x);
        }
        else if(op==3)
        {
            // cout<<tx_min(x)+1<<'\n';
            print(tx_min(x)+1);
            puts("");
        }
        else if(op==4)
        {
            // cout<<tr[tx_rank(x)].val<<'\n';
            print(tr[tx_rank(x)].val);
            puts("");
        }
        else if(op==5)
        {
            // cout<<tr[tx_q(x)].val<<'\n';
            print(tr[tx_q(x)].val);
            puts("");
        }
        else
        {
            // cout<<tr[tx_h(x)].val<<'\n';
            print(tr[tx_h(x)].val);
            puts("");
        }
    }
}

无旋 treap

#include<bits/stdc++.h>
#define int long long
using namespace std;
char buf[1 << 20], *p1, *p2;
#define gc()                                                               \
  (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) \
       ? EOF                                                               \
       : *p1++)
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
inline void print(int x)
{
    if (x<0)
    {
        putchar('-');x=-x;
    }
    if (x>9) print(x/10);
    putchar(x%10+'0');
}
mt19937 rd;
const int M=100000000;
struct node{
    int l,r,v,sz,w;
}tr[2222222];
void tupdata(int root)
{
    if(root)
    {
        tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+1;
    }
}
void tsplit(int root,int v,int &x,int &y)
{
    if(!root)
    {
        x=y=0;
        return;
    }
    if(tr[root].v<=v)
    {
        x=root;
        tsplit(tr[root].r,v,tr[x].r,y);
    }
    else
    {
        y=root;
        tsplit(tr[root].l,v,x,tr[y].l);
    }
    tupdata(root);
}
void tmerge(int &root,int x,int y)
{
    if(!x or !y)
    {
        root=x+y;
    }
    else if(tr[x].w>=tr[y].w)
    {
        root=x;
        tmerge(tr[root].r,tr[x].r,y);
    }
    else
    {
        root=y;
        tmerge(tr[root].l,x,tr[y].l);
    }
    tupdata(root);
}
int root,c;
void tinsert(int &root,int v)
{
    int w,x,y,z;
    w=x=y=0;
    z=++c;
    tr[z]={0,0,v,1,rd()%M};
    tsplit(root,v,x,y);
    tmerge(w,x,z);
    tmerge(root,w,y);
}
void tdelete(int v)
{
    int x,y,z,w,p;
    x=y=z=w=p=0;
    tsplit(root,v,x,y);
    tsplit(x,v-1,z,w);
    tmerge(w,tr[w].l,tr[w].r);
    tupdata(x);
    tmerge(p,z,w);
    tmerge(root,p,y);
}
int tx_min(int v)
{
    int x,y;
    x=y=0;
    tsplit(root,v-1,x,y);
    int ans=tr[x].sz+1;
    tmerge(root,x,y);
    return ans;
}
int tx_rank(int root,int x)
{
    if(x<=tr[tr[root].l].sz)
    {
        return tx_rank(tr[root].l,x);
    }
    if(x==tr[tr[root].l].sz+1)
    {
        return tr[root].v;
    }
    return tx_rank(tr[root].r,x-tr[tr[root].l].sz-1);
}
int tx_q(int v)//
{
    int x,y;
    x=y=0;
    tsplit(root,v-1,x,y);
    int ans=tx_rank(x,tr[x].sz);
    tmerge(root,x,y);
    return ans;
}
int tx_h(int v)//
{
    int x,y;
    x=y=0;
    tsplit(root,v,x,y);
    int ans=tx_rank(y,1);
    tmerge(root,x,y);
    return ans;
}
int n;
signed main()
{
    srand(time(0));
    n=read();
    for(int i=1,op,x;i<=n;i++)
    {
        op=read();
        x=read();
        if(op==1)
        {
            tinsert(root,x);
        }
        else if(op==2)
        {
            tdelete(x);
        }
        else if(op==3)
        {
            print(tx_min(x));
            puts("");
        }
        else if(op==4)
        {
            print(tx_rank(root,x));
            puts("");
        }
        else if(op==5)
        {
            print(tx_q(x));
            puts("");
        }
        else
        {
            print(tx_h(x));
            puts("");
        }
    }
}

AVL 树

#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
using namespace std;
int root;
struct node{
    int l,r,v,h,cnt,sz;
}tr[111111];
void zag(int &root)
{
    int tx=tr[root].r;
    tr[root].r=tr[tx].l;
    tr[tx].l=root;
    tr[root].h=max(tr[tr[root].l].h,tr[tr[root].r].h)+1;
    tr[tx].h=max(tr[tr[tx].l].h,tr[tr[tx].r].h)+1;
    tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+tr[root].cnt;
    tr[tx].sz=tr[tr[tx].l].sz+tr[tr[tx].r].sz+tr[tx].cnt;
    root=tx;
}
void zig(int &root)
{
    int tx=tr[root].l;
    tr[root].l=tr[tx].r;
    tr[tx].r=root;
    tr[root].h=max(tr[tr[root].l].h,tr[tr[root].r].h)+1;
    tr[tx].h=max(tr[tr[tx].l].h,tr[tr[tx].r].h)+1;
    tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+tr[root].cnt;
    tr[tx].sz=tr[tr[tx].l].sz+tr[tr[tx].r].sz+tr[tx].cnt;
    root=tx;
}
void zagzig(int &root)
{
    zag(tr[root].l);
    zig(root);
}
void zigzag(int &root)
{
    zig(tr[root].r);
    zag(root);
}
int c;
void tinsert(int &root,int x)
{
    if(!root)
    {
        root=++c;
        tr[root].v=x;
        tr[root].cnt=tr[root].sz=tr[root].h=1;
        return;
    }
    if(x<tr[root].v)
    {
        tinsert(tr[root].l,x);
        if(tr[tr[root].l].h==tr[tr[root].r].h+2)
        {
            if(x<tr[tr[root].l].v)
            {
                zig(root);
            }
            else
            {
                zagzig(root);
            }
        }
    }
    else if(x>tr[root].v)
    {
        tinsert(tr[root].r,x);
        if(tr[tr[root].l].h==tr[tr[root].r].h-2)
        {
            if(x>tr[tr[root].r].v)
            {
                zag(root);
            }
            else
            {
                zigzag(root);
            }
        }
    }
    else
    {
        tr[root].sz++;
        tr[root].cnt++;
    }
    tr[root].h=max(tr[tr[root].l].h,tr[tr[root].r].h)+1;
    tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+tr[root].cnt;
}
void tupdata(int &root)
{
    if(tr[tr[root].l].h==tr[tr[root].r].h+2)
    {
        int x=tr[root].l;
        if(tr[tr[x].l].h==tr[tr[root].r].h+1)
        {
            zig(root);
        }
        else
        {
            zagzig(root);
        }
    }
    else if(tr[tr[root].l].h==tr[tr[root].r].h-2)
    {
        int x=tr[root].r;
        if(tr[tr[x].r].h==tr[tr[root].l].h+1)
        {
            zag(root);
        }
        else
        {
            zigzag(root);
        }
    }
    tr[root].h=max(tr[tr[root].l].h,tr[tr[root].r].h)+1;
    tr[root].sz=tr[tr[root].l].sz+tr[tr[root].r].sz+tr[root].cnt;
}
pii tdelete(int &root,int x)
{
    int tx,ty;
    if(tr[root].v==x or (tr[root].v<x and tr[root].r==0))
    {
        if(tr[root].v==x and tr[root].cnt>1)
        {
            tr[root].sz--;
            tr[root].cnt--;
        }
        else if(tr[root].l==0 or tr[root].r==0)
        {
            tx=tr[root].v;
            ty=tr[root].cnt;
            root=tr[root].l+tr[root].r;
            return {tx,ty};
        }
        else
        {
            pii tt=tdelete(tr[root].l,x);
            tr[root].v=tt.first;
            tr[root].cnt=tt.second;
        }
    }
    else
    {
        if(x<tr[root].v)
        {
            pii tt=tdelete(tr[root].l,x);
            tx=tt.first;
            ty=tt.second;
        }
        else
        {
            pii tt=tdelete(tr[root].r,x);
            tx=tt.first;
            ty=tt.second;
        }
    }
    if(root!=0)
    {
        tupdata(root);
    }
    return {tx,ty};
}
bool tfind(int x)
{
    int rt=root;
    while(rt!=0 and tr[rt].v!=x)
    {
        if(x<tr[rt].v)
        {
            rt=tr[rt].l;
        }
        else
        {
            rt=tr[rt].r;
        }
    }
    return rt;
}
int tx_min(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x<=tr[rt].v)
        {
            rt=tr[rt].l;
        }
        else
        {
            ans+=tr[tr[rt].l].sz+tr[rt].cnt;
            rt=tr[rt].r;
        }
    }
    return ans;
}
int tx_rank(int x)
{
    int rt=root;
    while(rt!=0)
    {
        if(tr[tr[rt].l].sz<x)
        {
            if(tr[tr[rt].l].sz+tr[rt].cnt>=x)
            {
                return rt;
            }
            else
            {
                x-=(tr[tr[rt].l].sz+tr[rt].cnt);
                rt=tr[rt].r;
            }
        }
        else
        {
            rt=tr[rt].l;
        }
    }
    return 0;
}
int tx_q(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x>tr[rt].v)
        {
            ans=rt;
            rt=tr[rt].r;
        }
        else
        {
            rt=tr[rt].l;
        }
    }
    return ans;
}
int tx_h(int x)
{
    int rt=root,ans=0;
    while(rt!=0)
    {
        if(x<tr[rt].v)
        {
            ans=rt;
            rt=tr[rt].l;
        }
        else
        {
            rt=tr[rt].r;
        }
    }
    return ans;
}
int n;
signed main()
{
    cin>>n;
    for(int i=1,op,x;i<=n;i++)
    {
        cin>>op>>x;
        if(op==1)
        {
            tinsert(root,x);
        }
        else if(op==2)
        {
            if(!tfind(x))
            {
                continue;
            }
            tdelete(root,x);
        }
        else if(op==3)
        {
            cout<<tx_min(x)+1<<'\n';
        }
        else if(op==4)
        {
            cout<<tr[tx_rank(x)].v<<'\n';
        }
        else if(op==5)
        {
            cout<<tr[tx_q(x)].v<<'\n';
        }
        else
        {
            cout<<tr[tx_h(x)].v<<'\n';
        }
    }
}

splay

#include<bits/stdc++.h>
#define int long long
using namespace std;
char buf[1 << 20], *p1, *p2;
#define gc()                                                               \
  (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) \
       ? EOF                                                               \
       : *p1++)
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
inline void print(int x)
{
    if (x<0)
    {
        putchar('-');x=-x;
    }
    if (x>9) print(x/10);
    putchar(x%10+'0');
}
struct node{
    int son[2],fa,v,cnt,sz;
}tr[2222222];
void tupdata(int root)
{
    tr[root].sz=tr[tr[root].son[0]].sz+tr[tr[root].son[1]].sz+tr[root].cnt;
}
void trotate(int x)
{
    int y=tr[x].fa,z=tr[y].fa;
    int op=(tr[y].son[1]==x);
    tr[z].son[tr[z].son[1]==y]=x;
    tr[x].fa=z;
    tr[y].son[op]=tr[x].son[op^1];
    tr[tr[x].son[op^1]].fa=y;
    tr[x].son[op^1]=y;
    tr[y].fa=x;
    tupdata(y);
    tupdata(x);
}
int root,c;
void tsplay(int x,int f)
{
    while(tr[x].fa!=f)
    {
        int y=tr[x].fa,z=tr[y].fa;
        if(z!=f)
        {
            (tr[y].son[0]==x)^(tr[z].son[0]==y)?trotate(x):trotate(y);
        }
        trotate(x);
    }
    if(!f)
    {
        root=x;
    }
}
void tinsert(int x)
{
    int rt=root,p=0;
    while(tr[rt].v!=x and rt)
    {
        p=rt;
        rt=tr[rt].son[x>tr[rt].v];
    }
    if(rt)
    {
        tr[rt].cnt++;
    }
    else
    {
        rt=++c;
        tr[p].son[x>tr[p].v]=rt;
        tr[rt].fa=p;
        tr[rt].v=x;
        tr[rt].cnt=tr[rt].sz=1;
    }
    tsplay(rt,0);
}
void tfind(int x)
{
    int rt=root;
    while(tr[rt].son[x>tr[rt].v] and x!=tr[rt].v)
    {
        rt=tr[rt].son[x>tr[rt].v];
    }
    tsplay(rt,0);
}
int tx_q(int x)
{
    tfind(x);
    int rt=root;
    if(tr[rt].v<x)
    {
        return rt;
    }
    rt=tr[rt].son[0];
    while(tr[rt].son[1])
    {
        rt=tr[rt].son[1];
    }
    tsplay(rt,0);
    return rt;
}
int tx_h(int x)
{
    tfind(x);
    int rt=root;
    if(tr[rt].v>x)
    {
        return rt;
    }
    rt=tr[rt].son[1];
    while(tr[rt].son[0])
    {
        rt=tr[rt].son[0];
    }
    tsplay(rt,0);
    return rt;
}
void tdelete(int x)
{
    int y=tx_q(x),z=tx_h(x);
    tsplay(y,0);
    tsplay(z,y);
    int t=tr[z].son[0];
    if(tr[t].sz>1)
    {
        tr[t].cnt--;
        tsplay(t,0);
    }
    else
    {
        tr[z].son[0]=0;
        tsplay(z,0);
    }
}
int tx_rank(int x)
{
    tinsert(x);
    int ans=tr[tr[root].son[0]].sz;
    tdelete(x);
    return ans;
}
int tx_min(int x)
{
    int rt=root;
    while(rt)
    {
        if(tr[tr[rt].son[0]].sz<x)
        {
            if(tr[tr[rt].son[0]].sz+tr[rt].cnt>=x)
            {
                break;
            }
            else
            {
                x-=tr[tr[rt].son[0]].sz+tr[rt].cnt;
                rt=tr[rt].son[1];
            }
        }
        else
        {
            rt=tr[rt].son[0];
        }
    }
    tsplay(rt,0);
    return rt;
}
int n;
signed main()
{
    tinsert(1145141919);
    tinsert(-1145141919);
    n=read();
    for(int i=1,op,x;i<=n;i++)
    {
        op=read();
        x=read();
        if(op==1)
        {
            tinsert(x);
        }
        else if(op==2)
        {
            tdelete(x);
        }
        else if(op==3)
        {
            print(tx_rank(x));
            puts("");
        }
        else if(op==4)
        {
            print(tr[tx_min(x+1)].v);
            puts("");
        }
        else if(op==5)
        {
            print(tr[tx_q(x)].v);
            puts("");
        }
        else
        {
            print(tr[tx_h(x)].v);
            puts("");
        }
    }
}

可持久化数据结构

可持久化线段树

P3919 【模板】可持久化线段树 1(可持久化数组)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1111111;
int rts;
int a[N],tr[N<<5],ls[N<<5],rs[N<<5],r[N<<5];
void build(int &rt,int l,int rr)
{
    if(!rt)
    {
        rt=++rts;
    }
    if(l==rr)
    {
        tr[rt]=a[l];
        return;
    }
    int mid=(l+rr)/2;
    build(ls[rt],l,mid);
    build(rs[rt],mid+1,rr);
}
void change(int rt1,int &rt2,int l,int rr,int x,int y)
{
    if(!rt2)
    {
        rt2=++rts;
    }
    if(l==rr)
    {
        tr[rt2]=y;
        return;
    }
    int mid=(l+rr)/2;
    if(x<=mid)
    {
        rs[rt2]=rs[rt1];
        change(ls[rt1],ls[rt2],l,mid,x,y);
    }
    else
    {
        ls[rt2]=ls[rt1];
        change(rs[rt1],rs[rt2],mid+1,rr,x,y);
    }
}
int sum(int rt,int l,int rr,int x)
{
    if(l==rr)
    {
        return tr[rt];
    }
    int mid=(l+rr)/2;
    if(x<=mid)
    {
        return sum(ls[rt],l,mid,x);
    }
    else
    {
        return sum(rs[rt],mid+1,rr,x);
    }
}
int n,m;
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    build(r[0],1,n);
    for(int i=1,v,op,loc,val;i<=m;i++)
    {
        cin>>v>>op>>loc;
        if(op==1)
        {
            cin>>val;
            change(r[v],r[i],1,n,loc,val);
        }
        else
        {
            int s=sum(r[v],1,n,loc);
            cout<<s<<'\n';
            r[i]=++rts;
            ls[r[i]]=ls[r[v]];
            rs[r[i]]=rs[r[v]];
        }
    }
}

P3834 【模板】可持久化线段树 2

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=222222;
int rts;
int a[N],ls[N<<5],rs[N<<5],r[N<<5],s[N<<5];
void change(int rt1,int &rt2,int l,int rr,int x)
{
    if(!rt2)
    {
        rt2=++rts;
    }
    s[rt2]=s[rt1]+1;
    if(l==rr)
    {
        return;
    }
    int mid=(l+rr)/2;
    if(x<=mid)
    {
        rs[rt2]=rs[rt1];
        change(ls[rt1],ls[rt2],l,mid,x);
    }
    else
    {
        ls[rt2]=ls[rt1];
        change(rs[rt1],rs[rt2],mid+1,rr,x);
    }
}
int sum(int rt1,int rt2,int l,int rr,int x)
{
    if(l==rr)
    {
        return l;
    }
    int ss=s[ls[rt2]]-s[ls[rt1]],mid=(l+rr)/2;
    if(x<=ss)
    {
        return sum(ls[rt1],ls[rt2],l,mid,x);
    }
    else
    {
        return sum(rs[rt1],rs[rt2],mid+1,rr,x-ss);
    }
}
int n,m;
int b[N];
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b+1,b+1+n);
    int c=unique(b+1,b+1+n)-b;
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(b+1,b+1+c,a[i])-b;
    }
    for(int i=1;i<=n;i++)
    {
        change(r[i-1],r[i],1,n,a[i]);
    }
    for(int i=1,l,rr,x;i<=n;i++)
    {
        cin>>l>>rr>>x;
        cout<<b[sum(r[l-1],r[rr],1,n,x)]<<'\n';
    }
}

数学

数论

最大公约数

扩展欧几里得算法

int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a; 
    }
    int ret=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*x;
    return ret;
}

Stein 算法

int gcd(int a,int b)
{
    if(a<b)
    {
        swap(a,b);
    }
    if(!b)
    {
        return a;
    }
    if(!(a&1) and !(b&1))
    {
        return gcd(a>>1,b>>1)<<1;
    }
    else if((a&1) and !(b&1))
    {
        return gcd(a,b>>1);
    }
    else if(!(a&1) and (b&1))
    {
        return gcd(a>>1,b);
    }
    else
    {
        return gcd(a-b,b);
    }
}

筛法

埃筛

vector<int> prime;
bool is_prime[N];
void Eratosthenes(int n)
{
    is_prime[0]=is_prime[1]=0;
    for(int i=2;i<=n;++i)
    {
        is_prime[i]=1;
    }
    for(int i=2;i<=n;++i)
    {
        if(is_prime[i])
        {
            prime.push_back(i);
            if((long long)i*i>n)
            {
                continue;
            }
            for(int j=i*i;j<=n;j+=i)
            {
                is_prime[j]=0;
            }
        }
    }
}

埃筛+bitset优化

vector<int> prime;
bitset<N>is_prime;
void Eratosthenes(int n)
{
    is_prime[0]=is_prime[1]=0;
    for(int i=2;i<=n;++i)
    {
        is_prime[i]=1;
    }
    for(int i=2;i<=n;++i)
    {
        if(is_prime[i])
        {
            prime.push_back(i);
            if((long long)i*i>n)
            {
                continue;
            }
            for(int j=i*i;j<=n;j+=i)
            {
                is_prime[j]=0;
            }
        }
    }
}

欧拉筛

vector<int> pri;
bool not_prime[N];
void pre(int n)
{
    for(int i=2;i<=n;++i)
    {
        if(!not_prime[i])
        {
            pri.push_back(i);
        }
        for(int pri_j:pri)
        {
            if(i*pri_j>n)
            {
                break;
            }
            not_prime[i*pri_j]=1;
            if(!(i%pri_j))
            {
                break;
            }
        }
    }
}

欧拉筛+bitset优化

vector<int> pri;
bitset<N>not_prime;
void pre(int n)
{
    for(int i=2;i<=n;++i)
    {
        if(!not_prime[i])
        {
            pri.push_back(i);
        }
        for(int pri_j:pri)
        {
            if(i*pri_j>n)
            {
                break;
            }
            not_prime[i*pri_j]=1;
            if(!(i%pri_j))
            {
                break;
            }
        }
    }
}

筛法求欧拉函数

vector<int>pri;
bool not_prime[N];
int phi[N];
void pre(int n)
{
    phi[1]=1;
    not_prime[0]=not_prime[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!not_prime[i])
        {
            pri.push_back(i);
            phi[i]=i-1;
        }
        for(auto j:pri)
        {
            if(i*j>n)
            {
                break;
            }
            not_prime[i*j]=1;
            if(i%j==0)
            {
                phi[i*j]=phi[i]*j;
                break;
            }
            phi[i*j]=phi[i]*phi[j];
        }
    }
}

欧拉函数

int euler_phi(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%2==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0)
            {
                n/=i;
            }
        }
    }
    if(n>1)
    {
        ans=ans/n*(n-1);
    }
    return ans;
}

卢卡斯定理

int lcs(int n,int m)
{
    if(m==0)
    {
        return 1;
    }
    return (c(n%M,m%M)*lcs(n/M,m/M))%M;
}

组合数学

排列组合

C(n,m)

int qpow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=ans*a%M;
        }
        b>>=1;
        a=a*a%M;
    }
    return ans;
}
int c(int n,int m)
{
    if(n<m)
    {
        return 0;
    }
    int a=1,b=1;
    for(int i=n-m+1;i<=n;i++)
    {
        a=a*i%M;
    }
    for(int i=2;i<=m;i++)
    {
        b=b*i%M;
    }
    return a*qpow(b,M-2)%M;
}

杂项

优化

指令集优化

#define __AVX__ 1
#define __AVX2__ 1
#define __SSE__ 1
#define __SSE2__ 1
#define __SSE2_MATH__ 1
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSE_MATH__ 1
#define __SSSE3__ 1

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")

#include <immintrin.h>
#include <emmintrin.h>

快读

整型

char buf[1 << 20], *p1, *p2;
#define gc()                                                               \
  (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) \
       ? EOF                                                               \
       : *p1++)
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

字符串

bool check(char a) { return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'); }
inline string readstr() {
    string s;
    char aa = getchar();
    while (!check(aa)) aa = getchar();
    while (check(aa)) s += aa, aa = getchar();
    return s;
}

快输

整型

inline void print(int x)
{
    if (x<0)
    {
        putchar('-');x=-x;
    }
    if (x>9) print(x/10);
    putchar(x%10+'0');
}

图论

最小生成树

P3366 【模板】最小生成树

#include<bits/stdc++.h>
#define int long long
using namespace std;
int head[222222],cnt=2;
struct node{
    int from,to,nxt,val;
}e[522222];
void add_edge(int x,int y,int z)
{
    e[++cnt].to=y,e[cnt].nxt=head[x],head[x]=cnt,e[cnt].val=z,e[cnt].from=x;
}
bool cmp(node a,node b)
{
    return a.val<b.val;
}
int f[222222],w[222222];
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
int n,m;
signed main()
{
    memset(head,-1,sizeof(head));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
        w[i]=1;
    }
    for(int i=1,x,y,z;i<=m;i++)
    {
        cin>>x>>y>>z;
        add_edge(x,y,z);
    }
    int s=0;
    sort(e,e+cnt,cmp);
    for(int i=3;i<=cnt;i++)
    {
        int x=e[i].from,y=e[i].to;
        x=find(x),y=find(y);
        if(x==y)
        {
            continue;
        }
        f[x]=y;
        w[y]+=w[x];
        s+=e[i].val;
    }
    if(w[find(1)]!=n)
    {
        cout<<"orz";
    }
    else
    {
        cout<<s;
    }
}

最短路

Floyd 算法

B3647 【模板】Floyd

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
int n,m,x,y,z;
int dis[105][105];
signed main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(i==j)
            {
                dis[i][j]=0;
            }
            else
            {
                dis[i][j]=inf;
            }
        }
    }
    for(int i=1; i<=m; i++)
    {
        cin>>x>>y>>z;
        dis[x][y]=z;
        dis[y][x]=z;
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            cout<<dis[i][j]<<" ";
        }
        cout<<endl;
    }
}

Bellman–Ford 算法

队列优化:SPFA

P3385 【模板】负环

#include<bits/stdc++.h>
#define int long long
using namespace std;
int T;
void init();
void work();
signed main()
{
    cin>>T;
    while(T--)
    {
        init();
        work();
    }
}
int head[222222];
struct node{
    int to,nxt,v;
}e[222222];
queue<int>q;
bitset<222222>vis;
int cnt1=2;
void add_edge(int x,int y,int z)
{
    e[++cnt1].to=y,e[cnt1].nxt=head[x],head[x]=cnt1,e[cnt1].v=z;
}
int n,m;
int dis[222222];
int cnt[222222];
void init()
{
    cnt1=2;
    while(!q.empty())
    {
        q.pop();
    }
    memset(head,-1,sizeof(head));
    memset(dis,0x3f,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    vis.reset();
}
void spfa(int s)
{
    memset(dis,0x3f,sizeof(dis));
    vis[s]=1,dis[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].v)
            {
                dis[y]=dis[x]+e[i].v;
                cnt[y]=cnt[x]+1;
                if(cnt[y]>=n)
                {
                    cout<<"YES";
                    return;
                }
                if(!vis[y])
                {
                    vis[y]=1;
                    q.push(y);
                }
            }
        }
    }
    cout<<"NO";
}
void work()
{
    cin>>n>>m;
    for(int i=1,x,y,z;i<=m;i++)
    {
        cin>>x>>y>>z;
        add_edge(x,y,z);
        if(z>=0)
        {
            add_edge(y,x,z);
        }
    }
    spfa(1);
    puts("");
}

队列优化:SPFA(SLF优化)

int head[222222];
struct node{
    int to,nxt,v;
}e[222222];
deque<int>q;
bitset<222222>vis;
int cnt=2;
void add_edge(int x,int y,int z)
{
    e[++cnt].to=y,e[cnt].nxt=head[x],head[x]=cnt,e[cnt].v=z;
}
int dis[222222];
void spfa(int s)
{
    memset(dis,0x3f,sizeof(dis));
    vis[s]=1,dis[s]=0;
    q.push_back(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop_front();
        vis[x]=0;
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].v)
            {
                dis[y]=dis[x]+e[i].v;
                if(!vis[y])
                {
                    vis[y]=1;
                    if(!q.empty() and dis[q.front()]>dis[y])
                    {
                        q.push_front(y);
                    }
                    else
                    {
                        q.push_back(y);
                    }
                }
            }
        }
    }
}

Dijkstra 算法

P3371 【模板】单源最短路径(弱化版)

P4779 【模板】单源最短路径(标准版)

#include <bits/stdc++.h>
#define int long long
using namespace std;
int head[222222], cnt = 2;
struct node {
    int to, nxt, val;
} e[522222];
void add_edge(int x, int y, int z) { e[++cnt].to = y, e[cnt].nxt = head[x], head[x] = cnt, e[cnt].val = z; }
//
int dis[222222];
void dij(int xx);
void dfs(int x, int dis);
//
int n, m, s;
signed main() {
    memset(head,-1,sizeof(head));
    cin >> n >> m>>s;
    for (int i = 1, x, y, z; i <= m; i++) {
        cin >> x >> y >> z;
        add_edge(x, y, z);
    }
    dij(s);
    for(int i=1;i<=n;i++)
    {
        cout<<dis[i]<<" ";
    }
}
// dij
struct node1 {
    int dis, to;
    bool operator>(const node1 &T) const { return dis > T.dis; }
};
bitset<222222> vis;
priority_queue<node1, vector<node1>, greater<node1> > q;
void dij(int xx) {
    memset(dis, 0x3f, sizeof(dis));
    q.push({ 0, xx });
    vis.reset();
    dis[xx] = 0;
    while (!q.empty()) {
        int x = q.top().to;
        q.pop();
        if (vis[x]) {
            continue;
        }
        vis[x] = 1;
        for (int i = head[x]; i!=-1; i = e[i].nxt) {
            int y = e[i].to;
            if(vis[y])
            {
                continue;
            }
            if (dis[y] > dis[x] + e[i].val) {
                dis[y] = dis[x] + e[i].val;
                q.push({dis[y] ,y});
            }
        }
    }
}

连通性相关

割点和桥

P3388 【模板】割点(割顶)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int head[222222],cnt=2;
struct node{
    int to,nxt;
}e[222222];
void add_edge(int x,int y)
{
    e[++cnt].to=y,e[cnt].nxt=head[x],head[x]=cnt;
}
int ans;
bitset<222222>flag;
int low[222222],dfn[222222],tot;
bitset<222222>vis;
void tarjan(int x,int fa)
{
    vis[x]=1;
    dfn[x]=low[x]=++tot;
    int son=0;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(!vis[y])
        {
            son++;
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(fa!=x and low[y]>=dfn[x] and !flag[x])
            {
                flag[x]=1;
                ans++;
            }
        }
        else if(y!=fa)
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(fa==x and son>=2 and !flag[x])
    {
        flag[x]=1;
        ans++;
    }
}
int n,m;
signed main()
{
    cin>>n>>m;
    for(int i=1,x,y;i<=m;i++)
    {
        cin>>x>>y;
        add_edge(x,y);
        add_edge(y,x);
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            tot=0;
            tarjan(i,i);
        }
    }
    cout<<ans<<endl;
    for(int i=1;i<=n;i++)
    {
        if(flag[i])
        {
            cout<<i<<" ";
        }
    }
}

割边

int ans;
bitset<222222>flag;
int low[222222],dfn[222222],tot;
void tarjan(int x,int fa)
{
    dfn[x]=low[x]=++tot;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(!dfn[y])
        {
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(low[y]>dfn[x])
            {
                flag[x]=1;
                ans++;
            }
        }
        else if(y!=fa and dfn[y]<dfn[x])
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
}

双联通分量

P8435 【模板】点双连通分量

#include<bits/stdc++.h>
#define int long long
using namespace std;
int head[6666666],cnt=2;
struct node{
    int to,nxt;
}e[6666666];
void add_edge(int x,int y)
{
    e[++cnt].to=y,e[cnt].nxt=head[x],head[x]=cnt;
}
int tot;
int dfn[6666666],low[6666666];
stack<int>q;
int ans;
vector<int>s[6666666];
void tarjan(int x,int fa)
{
    dfn[x]=low[x]=++tot;
    int son=0;
    q.push(x);
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(!dfn[y])
        {
            ++son;
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x])
            {
                ans++;
                while(!q.empty() and q.top()!=y)
                {
                    s[ans].push_back(q.top());
                    q.pop();
                }
                s[ans].push_back(x);
                s[ans].push_back(y);
                q.pop();
            }
        }
        else if(y!=fa)
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(son==0 and fa==0)
    {
        s[++ans].push_back(x);
    }
}
int n,m;
signed main()
{
    cin>>n>>m;
    for(int i=1,x,y;i<=m;i++)
    {
        cin>>x>>y;
        add_edge(x,y);
        add_edge(y,x);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        {
            tot=0;
            tarjan(i,0);
        }
    }
    cout<<ans<<'\n';
    for(int i=1;i<=ans;i++)
    {
        cout<<s[i].size()<<" ";
        for(auto j:s[i])
        {
            cout<<j<<" ";
        }
        cout<<'\n';
    }
}

P8436 【模板】边双连通分量

本文分类参照OI Wiki~