【基本算置顶】各大算法&&数据结构模板

板子,全是板子

更新日志(从2018.11.19开始)

2018.12.02 : 更新了数据结构->扫描线
2018.11.22 : 更新了数据结构->平衡树->FHQ Treap->维护区间操作
2018.11.20 : 更新了数论->博弈论->nim游戏
2018.11.20 : 更新了数据结构->平衡树->FHQ Treap

观摩本蒟蒻板子库的大佬数:

不断更新

一.数论

    1.快速幂
    2.欧拉函数
    3.乘法逆元(线性求逆)
    4.线性筛素数
    5.扩展欧几里得
    6.求单个数的逆元
    7.矩阵加速
    8.整除分块
    9.博弈论
        (1)nim游戏

二.图论

    1.并查集
    2.Kruskal算法
    3.Dijkstra算法(优化版)
    4.SPFA算法
    5.Floyd(已优化)
    6.二分图染色
    7.拓扑排序
    8.缩点(tarjan求强联通分量)

三.数据结构

    1.堆
    2.线段树
        ex:线段树优化Dijkstra
    3.(ex_线段树)zkw线段树
    4.树状数组
    5.LCA(最近公共祖先)
        (1)倍增
        (2)树链剖分
    6.平衡树
        (1)Treap
        (2)Splay
        (3)FHQ Treap
    7.权值线段树
    8.主席树(可持久化(权值)线段树)
    9.可持久化数组(可持久化线段树)
    10.二维树状数组
    11.扫描线

四.其他

    (一)字符串算法

        1.manacher算法
        2.Trie树
        3.字符串hash
            (1)自然溢出法
            (2)单模哈希法
            (3)双模哈希法
        4.KMP字符串匹配

    (二)排序算法

        1.归并排序
        2.快速排序
        3.堆排序
        4.冒泡排序

    (三)DP算法

        1.LCS(最长公共子序列)

    (四)树上算法

        1.树链剖分

一.数论

1.快速幂

inline ll mul(ll a,ll b,ll mod){
    ll ans=1;
    while(b){
        if(b&1) ans=ans*a%p;
        a=a*a%p;    b>>=1;
    }
    return ans%mod;
}

2.欧拉函数

inline ll phi(ll n){
    ll ans=n;
    for(int i=2;i*i<=n;i++){
        if(n%i==0)  ans=ans/i*(i-1);
        while(n%i==0)   n/=i;
    }
    if(n!=1)    ans=ans/n*(n-1);
    return ans;
}

3.乘法逆元(线性求逆)

P3811【模板】乘法逆元——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 20010020
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll inv[mn],n,p;
int main(){
    n=read(),p=read();
    inv[1]=1;
    cout<<1<<"\n";
    go(i,2,n,1){
        inv[i]=(-1*((p/i)*inv[p%i])%p+p)%p;
        printf("%d\n",inv[i]);
    }
    return 0;
}

4.线性筛素数

(1)埃式筛法
P3383 【模板】线性筛素数——AC代码

//实质上这个算法不是所谓欧拉的线性筛;而是一个O(nlglgn)的算法,但是在数据很大时,由于这个算法的常数小,且lglgn在数据很大的情况下基本不变,所以在某种意义上这个算法好写且更优秀。

#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(int i=j;i>=n;i-=k)
#define mn 10000010
#define mm 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
bool prime[mn];
int n,m,a;
inline void primee(int nn){
    go(i,0,nn,1){
        prime[i]=true;
    }
    prime[0]=prime[1]=false;
    go(i,2,nn,1){
        if(!prime[i])
            continue;
        go(j,2*i,nn,i){
            prime[j]=false;
        }
    }
}
int main(){
    n=read();m=read();
    primee(n);
    go(i,1,m,1){
        a=read();
        if(prime[a])
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}
 
(2)欧拉筛法
P3383 【模板】线性筛素数——AC代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define ll long long
#define mn 10001000
#define inf 1 << 30
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int v[mn], prime[mn], m;
inline void get_prime(int n) {
    m = 0;
    go(i, 2, n, 1) {
        if(v[i] == 0) {
            v[i] = i;
            prime[++m] = i;
        }
        go(j, 1, m, 1) {
            if(prime[j] > v[i] || prime[j] > n / i) break;
            v[prime[j] * i] = prime[j];
        }
    }
}
int n, k;
int main() {
    n = read(), k = read();
    get_prime(n);
    go(i, 1, k, 1) {
        int x = read();
        if(v[x] == x) puts("Yes");
        else puts("No");
    }
    return 0;
}

5.扩展欧几里得

inline int ex_gcd(int a,int b,int &x,int &y){
    if(b==0){x=1;y=0;return a;}
    int g=ex_gcd(b,a%b,x,y);
    int tmp=y;
    y=x-y*(a/b);
    x=tmp;
    return g;
}

或者你如果不愿意记这么多的话:

void ex_gcd(int a, int b, int &x, int &y) {
    if(b) ex_gcd(b, a % b, y, x), y -= (a / b) * x;
    else x = 1, y = 0;
}

结束!

6.求单个数的逆元

P1082 同余方程——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline ll phi(ll n){
    ll ans=n;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            ans=ans/i*(i-1);
        }
        while(n%i==0)
            n/=i;
    }
    if(n!=1){
        ans=ans/n*(n-1);
    }
    return ans;
}
inline ll mul(ll a,ll b,ll mod){
    ll ans=1;
    while (b) {
        if (b&1) ans=ans*a%mod;
        a=a*a%mod;b>>=1;
    }
    return ans%mod;
}
ll a,b;
int main(){
    a=read(),b=read();
//  cout<<a<<" "<<b<<"\n";
    ll phin=phi(b);
    cout<<mul(a,phin-1,b);
    return 0;
}

7.矩阵加速

P1939 【模板】矩阵加速(数列)——AC代码

变量名是我萌机房的两位巨佬哦

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=e[i].next)
#define inf 1<<30
#define ll long long
#define mod 1000000007
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct mat {
    ll a[4][4];
    mat() { go(i, 1, 3, 1) go(j, 1, 3, 1) a[i][j] = 0; }
    void init() { go(i, 1, 3, 1) a[i][i] = 1; }
} wjs, jjq;
inline mat mat_mul(mat a, mat b) {
    mat ans;
    go(k, 1, 3, 1)  go(i, 1, 3, 1)  go(j, 1, 3, 1)
        ans.a[i][j] += a.a[i][k] * b.a[k][j] % mod, ans.a[i][j] %= mod;
    return ans;
}
inline mat mat_pow(mat a, ll b) {
    mat ans; ans.init();
    for(; b; b >>= 1) {
        if(b & 1) ans = mat_mul(ans, a);
        a = mat_mul(a, a);
    }
    return ans;
}
inline void mat_put(mat a) {
    go(i, 1, 3, 1) go(j, 1, 3, 1) printf("%lld%c", a.a[i][j], (j == 3) ? ‘\n‘ : ‘ ‘);
}
ll T, n;
int main(){
    T = read();
    while(T--) {
        n = read();
        if(n <= 3) { cout << "1\n"; continue; }
        wjs.a[1][1] = 1,wjs.a[2][1] = 0,wjs.a[3][1] = 1,
        wjs.a[1][2] = 1,wjs.a[2][2] = 0,wjs.a[3][2] = 0,
        wjs.a[1][3] = 0,wjs.a[2][3] = 1,wjs.a[3][3] = 0;
        jjq.a[1][1] = 1,jjq.a[1][2] = 0,jjq.a[1][3] = 0,
        jjq.a[2][1] = 1,jjq.a[2][2] = 0,jjq.a[2][3] = 0,
        jjq.a[3][1] = 1,jjq.a[2][3] = 0,jjq.a[3][3] = 0;
        // mat_put(jjq);
        // mat_put(wjs);
        mat QAQ = mat_pow(wjs, n - 3);
        // mat_put(QAQ);
        jjq = mat_mul(QAQ, jjq);
        cout << jjq.a[1][1] << "\n";
    }
    return 0;
}

8.整除分块

P2261 [CQOI2007]余数求和——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define inf 1 << 30
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
ll ans, n, k, sum;
int main(){
    n = read(), k = read();
    for (ll l = 1, r; l <= n; l = r + 1){
        if(k / l != 0)
            r = min(k / (k / l), n);
        else
            r = n;
        sum += (k / l) * (r - l + 1) * (l + r) / 2;
    }
    ans = n * k - sum;
    cout << ans;
    return 0;
}

9.博弈论

(1)nim游戏
P2197 【模板】nim游戏——AC代码
#include<iostream>
#include<cstdio>
using namespace std;
#define go(i,j,n,k) for(int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(int i=j;i>=n;i-=k)
#define rep(i,x) for(int i=h[x];i;i=e[i].nxt)
#define mn 10010
#define inf 1<<30
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int ans, x, n, T;
int main(){
    T = read();
    while(T--) {
        n = read();
        ans = 0;
        go(i, 1, n, 1) x = read(), ans ^= x;
        if(ans) puts("Yes");
        else puts("No");
    }
    return 0;
}

二.图论

1.并查集

P3367 【模板】并查集——AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define ll long long
#define mn 10010
#define inf 1 << 30
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int fa[mn], n, m;
inline int findx(int x) {
    if(x == fa[x]) return x;
    else return fa[x] = findx(fa[x]);
}
inline void mergex(int x, int y) {
    int xx = findx(x), yy = findx(y);
    if(xx == yy) return;
    if(rand() % 2) fa[xx] = yy;
    else fa[yy] = xx;
}
int main() {
    n = read(), m = read();
    go(i, 1, n, 1) fa[i] = i;
    go(i ,1, m, 1) {
        int s = read(), x = read(), y = read();
        if(s == 1) mergex(x, y);
        else {
            int xx = findx(x), yy = findx(y);
            if(xx == yy) puts("Y");
            else puts("N");
        }
    }
    return 0;
}

2.Kruskal算法

P3366 【模板】最小生成树——AC代码
#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=next[i])
#define inf 2147483647
#define mn 10010
#define mm 200010
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct edge
{
    int x,y,w;
} e[mm];
int n,m,b[mn],f[mn],sum=0,num=0;
inline int findx(int x)
{
    return f[x]==x?x:f[x]=findx(f[x]);
}
inline bool cmp(edge a,edge b)
{
    return a.w<b.w;
}
inline void Kru()
{
    go(i,1,n,1)
    {
        f[i]=i;
    }
    sort(e+1,e+m+1,cmp);
    go(i,1,m,1)
    {
        int u=findx(e[i].x);
        int v=findx(e[i].y);
        if(u!=v)
        {
            f[u]=v;
            sum+=e[i].w;
            num++;
            if(num==n-1)
                return ;
        }
    }
}
int main()
{
    n=read(),m=read();
    go(i,1,m,1)
    {
        e[i].x=read(),e[i].y=read(),e[i].w=read();
    }
    Kru();
    cout<<sum;
    return 0;
}

3.Dijkstra算法(优化版)

P3371 【模板】单源最短路径——AC代码
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 1 << 30
#define ll long long
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
inline void write(int x){
    if (x < 0)putchar(‘-‘);x = -x;
    if (x > 9)write(x / 10);
    putchar(x % 10 + ‘0‘);
}
//This is AC head above...
struct edge{
    int v, nxt, w;
} e[mn<<1];
int h[mn],p;
inline void add(int a,int b,int c){
    p++;
    e[p].nxt = h[a];
    h[a] = p;
    e[p].v = b;
    e[p].w = c;
}
struct node{
    int u,v;
    bool operator <(const node &b) const{
        return u > b.u;
    }
};
int n,m,s;
int dis[mn];
priority_queue<node> q;
inline void Dij(int s){
    go(i, 0, n, 1)
        dis[i] = inf;
    dis[s] = 0;
    node o;
    o.u = 0;
    o.v = s;
    q.push(o);
    while (q.size()){
        int u = q.top().v;
        int d = q.top().u;
        q.pop();
        if(d!=dis[u])
            continue;
        rep(i,u){
            int v = e[i].v;
            int w = e[i].w;
            if (dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                node p;
                p.u = dis[v], p.v = v;
                q.push(p);
            }
        }
    }
}
int main(){
    n=read(),m=read(),s=read();
    go(i,1,m,1){
        int u = read(), v = read(), w = read();
        add(u, v, w);
    }
    Dij(s);
    go(i,1,n,1){
        cout << dis[i] << " ";
    }
    cout << "\n";
    return 0;
}

4.SPFA算法

P3371 【模板】单源最短路径——AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=e[i].nxt)
#define mn 1000010
#define inf 2147483647
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct edge{
    int v,nxt,w;
}e[mn<<1];
int h[mn],p;
inline void add(int a,int b,int c){
    e[++p].nxt=h[a],h[a]=p,e[p].v=b,e[p].w=c;
}
int dis[mn],vis[mn],n,m,s,t;
inline void SPFA(int s){
    go(i,1,n,1)dis[i]=inf;
    queue<int> q;
    q.push(s),dis[s]=0,vis[s]=1;
    while(!q.empty()){
        int x=q.front();
        q.pop();vis[x]=0;
        rep(i,x){
            int v=e[i].v, w=e[i].w;
            if(dis[v] > dis[x] + w){
                dis[v] = dis[x] + w;
                if(!vis[v]){
                    q.push(v),vis[v]=1;
                }
            }
        }
    }
}
int main(){
    n=read(),m=read(),s=read();//t=read();
    go(i,1,m,1){
        int a=read(),b=read(),c=read();
        add(a,b,c);//add(b,a,c);
    }
    SPFA(s);
    //cout << dis[t] << "\n";
    go(i, 1, n, 1) printf("%d ", dis[i]);
    return 0;
}

5.Floyd(已优化)

P3371 【模板】单源最短路径——40分代码
#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 10010
#define inf 100000000
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int a[mn][mn],s,m,n,d,b,c;
inline void floyd(){
    go(k,1,n,1){
        go(i,1,n,1){
            if(i==k || a[i][k]==inf)
                continue;
            go(j,1,n,1){
                if(i==j || j==k || a[k][j]==inf)
                    continue;
                if(a[i][k]+a[k][j]<a[i][j]){
                    a[i][j]=a[i][k]+a[k][j];
                }
            }
        }
    }
}
int main(){
    n=read();m=read();s=read();
    go(i,1,n,1){
        go(j,1,n,1){
            a[i][j]=inf;
        }
    }
    go(i,1,m,1){
        d=read();b=read();c=read();
        a[d][b]=min(a[d][b],c);
    }
    floyd();
    go(i,1,n,1){
        if(i==s)
            cout<<"0 ";
        else if(a[s][i]==inf)
            cout<<"2147483647 ";
        else
            cout<<a[s][i]<<" ";
    }
    return 0;
}

6.二分图染色

bool vis[mk];
int c[mk];
vector<int> G[mk];
inline bool color(int u){
    vis[u]=true;
    go(i,0,G[u].size()-1,1){
        int v=G[u][i];
        if(vis[v]){
            if(c[v]!=c[u])
                return false;
        }else{
            c[v]=!c[u];
            if(!color(v))
                return false;
        }
    }
    return true;
}

7.拓扑排序

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define mm 500010
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct edge{ int v, nxt; } e[mm << 1]; int h[mn], p;
inline void add(int a, int b) { e[++p].nxt = h[a], h[a] = p, e[p].v = b; }
int n, m, du[mn];
vector<int> sorted;
queue<int> q;
inline void topsort() {
    go(i, 1, n, 1) if(!du[i]) q.push(i);
    while(!q.empty()) {
        int x = q.front(); q.pop();
        sorted.push_back(x);
        rep(i, x) {
            int v = e[i].v;
            if(!--du[v]) q.push(v);
        }
    }
}
int main() {
    n = read(), m = read();
    go(i, 1, m, 1) {
        int a = read(), b = read();
        add(a, b); du[b]++;
    }
    topsort();
    int sze = sorted.size();
    go(i, 0, sze - 1, 1)
        printf("%d ", sorted[i]);
    return 0;
}

8.缩点(tarjan求强联通分量)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 100100
#define inf 1 << 30
#define ll long long
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct edge{ int v, nxt; } e[mn << 1], ee[mn << 1]; int h[mn], p, hh[mn], pp;
inline void add(int a, int b) { e[++p].nxt = h[a], h[a] = p, e[p].v = b; }
inline void aadd(int a, int b) { ee[++pp].nxt = hh[a], hh[a] = pp, ee[pp].v = b; }
int dfn[mn], low[mn], co[mn], st[mn], top, cnt, ans, col, n, m, w[mn], b[mn], du[mn], dp[mn];
void tarjan(int x) {
    dfn[x] = low[x] = ++cnt;
    st[++top] = x;
    rep(i, x) {
        int v = e[i].v;
        if(!dfn[v]) {
            tarjan(v);
            low[x] = min(low[x], low[v]);
        } else if(!co[v]) {
            low[x] = min(low[x], dfn[v]);
        }
    }
    if(dfn[x] == low[x]) {
        ++col;
        while(st[top + 1] != x) {
            co[st[top]] = col;
            b[col] += w[st[top]];
            top--;
        }
    }
}
void dfs(int x, int f) {
    if(dp[x]) return;
    dp[x] = b[x];
    int maxx = 0;
    for(int i = hh[x]; i; i = ee[i].nxt) {
        int v = ee[i].v;
        if(v == f) continue;
        dfs(v, x);
        maxx = max(maxx, dp[v]);
    }
    dp[x] += maxx;
}
inline void debug() {
    go(i, 1, col, 1) printf("%d%c", b[i], (i == col) ? ‘\n‘ : ‘ ‘);
}
int main() {
    n = read(), m = read();
    go(i, 1, n, 1) w[i] = read();
    go(i, 1, m, 1) {
        int a = read(), b = read();
        add(a, b);
    }
    go(i, 1, n, 1) if(!dfn[i]) tarjan(i);
    go(x, 1, n, 1) {
        rep(i, x) {
            int v = e[i].v;
            if(co[x] != co[v])
                aadd(co[x], co[v]), du[co[v]]++;
        }
    }
    // debug();
    go(i, 1, col, 1) {
        if(!dp[i]) dfs(i, 0), ans = max(ans, dp[i]);
    }
    cout << ans << "\n";
    return 0;
}

三.数据结构

1.堆

P3378 【模板】堆——AC代码
#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;I-=k)
#define rep(i,x) for(register int i=h[x];i;i=last[x])
#define mn 30010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline void swap(int &a,int &b){
    int t=a;a=b;b=t;
}
int size,n,heap[mn];
inline void puth(int x){
    int now,next;
    heap[++size]=x;
    now=size;
    while(now>1){
        next=now>>1;
        if(heap[now]>=heap[next])
            return ;
        swap(heap[now],heap[next]);
        now=next;
    }
}
inline void geth(){
    cout<<heap[1]<<"\n";
    return ;
}
inline int delh(){
    int now,next,res;
    res=heap[1];
    heap[1]=heap[size--];
    now=1;
    while(now*2<=size){
        next=now*2;
        if(next<size && heap[next+1]<heap[next])
            next++;
        if(heap[now]<=heap[next])
            return res;
        swap(heap[now],heap[next]);
        now=next;
    }
}
int main(){
    n=read();
    go(i,1,n,1){
        int point=read(),a;
        switch(point){
            case 1:a=read();puth(a);break;
            case 2:geth();break;
            case 3:delh();break;
        }
    }
    return 0;
}

2.线段树

以下代码均为线段树。线段树太强辣!

列举如此多的线段树代码是强调线段树的重要性与用法

(1) P3374 【模板】树状数组 1 ——AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=next[i])
#define inf 1<<30
#define mn 500050
#define ll long long
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int z[mn*4];
int n,m;
inline void update(int rt){
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
inline void build(int l,int r,int rt){
    if(l==r){z[rt]=read();return ;}
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}
inline void modify(int l,int r,int rt,int p,int v){
    if(l==r){z[rt]+=v;return ;}
    int m=(l+r)>>1;
    if(p<=m)    modify(lson,p,v);
    else        modify(rson,p,v);
    update(rt);
}
inline int query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l && r<=nowr){return z[rt];}
    int m=(l+r)>>1;
    if(nowl<=m){
        if(m<nowr)
            return query(lson,nowl,nowr)+query(rson,nowl,nowr);
        else
            return query(lson,nowl,nowr);
    }else{
        return query(rson,nowl,nowr);
    }
}

int main(){
    n=read();
    m=read();
    build(root);
    go(i,1,m,1){
        int s=read();
        if(s==1){
            int x=read(),k=read();
            modify(root,x,k);
        } else if(s==2){
            int x=read(),y=read();
            cout<<query(root,x,y)<<"\n";
        }
    }
    return 0;
}
(2) P3368 【模板】树状数组 2 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=next[i])
#define inf 1<<30
#define mn 500010
#define ll long long
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll z[mn*4],col[mn*4];
inline void update(int rt){
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
inline void color(int l,int r,int rt,int v){
    z[rt]=z[rt]+(r-l+1)*v;
    col[rt]+=v;
}
inline void push_col(int l,int r,int rt){
    if(col[rt]!=0){
        ll m=(l+r)>>1;
        color(lson,col[rt]);
        color(rson,col[rt]);
        col[rt]=0;
    }
}
inline void build(int l,int r,int rt){
    if(l==r){z[rt]=read(),col[rt]=0;return ;}
    ll m=(l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}
inline void modify(int l,int r,int rt,int nowl,int nowr,int v){
    if(nowl<=l && r<=nowr){color(l,r,rt,v);return ;}
    ll m=(l+r)>>1;
    push_col(l,r,rt);
    if(nowl<=m) modify(lson,nowl,nowr,v);
    if(m<nowr)  modify(rson,nowl,nowr,v);
    update(rt);
}
inline ll query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l && r<=nowr){return z[rt];}
    push_col(l,r,rt);
    ll m=(l+r)>>1;
    if(nowl<=m){
        if(m<nowr)
            return query(lson,nowl,nowr)+query(rson,nowl,nowr);
        else
            return query(lson,nowl,nowr);
    }else{
        return query(rson,nowl,nowr);
    }
}
ll n,m;

int main(){
    n=read(),m=read();
    build(root);
    go(i,1,m,1){
        int s=read();
        if(s==1){
            ll x=read(),y=read(),k=read();
            modify(root,x,y,k);
        }else if(s==2){
            ll x=read()/*,y=read()*/;
            cout<<query(root,x,x/*y*/)<<"\n";
        }
    }
    return 0;
}
(3) P3372 【模板】线段树 1 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define inf 1<<30
#define mn 100010
#define ll long long
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll z[mn*4],col[mn*4];
inline void update(int rt){
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
inline void color(int l,int r,int rt,ll v){
    z[rt]=z[rt]+(r-l+1)*v;
    col[rt]+=v;
}
inline void push_col(int l,int r,int rt){
    if(col[rt]!=0){
        int m=(l+r)>>1;
        color(lson,col[rt]);
        color(rson,col[rt]);
        col[rt]=0;
    }
}
inline void build(int l,int r,int rt){
    if(l==r){z[rt]=read(),col[rt]=0;return ;}
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}
inline void modify(int l,int r,int rt,int nowl,int nowr,ll v){
    if(nowl<=l && r<=nowr){color(l,r,rt,v);return ;}
    int m=(l+r)>>1;
    push_col(l,r,rt);
    if(nowl<=m) modify(lson,nowl,nowr,v);
    if(m<nowr)  modify(rson,nowl,nowr,v);
    update(rt);
}
inline ll query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l && r<=nowr){return z[rt];}
    int m=(l+r)>>1;
    push_col(l,r,rt);
    if(nowl<=m){
        if(m<nowr)
            return query(lson,nowl,nowr)+query(rson,nowl,nowr);
        else
            return query(lson,nowl,nowr);
    } else{
        return query(rson,nowl,nowr);
    }
}
int n,m;
int main(){
    n=read();
    m=read();
    build(root);
    go(i,1,m,1){
        int s=read();
        if(s==1){
            int x=read(),y=read(),k=read();
            modify(root,x,y,k);
        }else{
            int x=read(),y=read();
            cout<<query(root,x,y)<<"\n";
        }
    }
    return 0;
}
(4) P3373 【模板】线段树 2 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=e[i].next)
#define mn 100010
#define inf 1<<30
#define ll long long
#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define bson l,r,rt
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll n,m,p;
struct node{
    ll add,mul;
} col[mn*4];
ll z[mn*4];int x,y;ll k;
inline void update(int rt){
    z[rt]=(z[rt<<1]+z[rt<<1|1])%p;
}
inline void color(int l,int r,int rt,ll add,ll mul){
    z[rt]=(z[rt]*mul)%p;
    z[rt]+=(r-l+1)*add;
    z[rt]%=p;
    col[rt].add*=mul;
    col[rt].add%=p;
    col[rt].add+=add;
    col[rt].add%=p;
    col[rt].mul*=mul;
    col[rt].mul%=p;
}
inline void push_col(int l,int r,int rt){
    if(col[rt].add!=0 || col[rt].mul!=1){
        int m=(l+r)>>1;
        color(lson,col[rt].add,col[rt].mul);
        color(rson,col[rt].add,col[rt].mul);
        col[rt].add=0;
        col[rt].mul=1;
    }
}
inline void build(int l,int r,int rt){
    col[rt].add=0,col[rt].mul=1;
    if(l==r){z[rt]=read();return ;}
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}
inline void modify_add(int l,int r,int rt,int nowl,int nowr,ll add){
    if(nowl<=l && r<=nowr){color(bson,add,1);return ;}
    int m=(l+r)>>1;
    push_col(bson);
    if(nowl<=m) modify_add(lson,nowl,nowr,add);
    if(m<nowr)  modify_add(rson,nowl,nowr,add);
    update(rt);
}
inline void modify_mul(int l,int r,int rt,int nowl,int nowr,ll mul){
    if(nowl<=l && r<=nowr){color(bson,0,mul);return ;}
    int m=(l+r)>>1;
    push_col(bson);
    if(nowl<=m) modify_mul(lson,nowl,nowr,mul);
    if(m<nowr)  modify_mul(rson,nowl,nowr,mul);
    update(rt);
}
inline ll query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l && r<=nowr){return z[rt]%p;}
    int m=(l+r)>>1;
    push_col(bson);
    if(nowl<=m){
        if(m<nowr)
            return (query(lson,nowl,nowr)+query(rson,nowl,nowr))%p;
        else
            return query(lson,nowl,nowr)%p;
    }else{
        return query(rson,nowl,nowr)%p;
    }
}
int main(){
    n=read(),m=read(),p=read();
    build(root);
    go(i,1,m,1){
        int s=read();
        switch(s){
            case 1:
                x=read(),y=read(),k=read();
                modify_mul(root,x,y,k);
                break;
            case 2:
                x=read(),y=read(),k=read();
                modify_add(root,x,y,k);
                break;
            case 3:
                x=read(),y=read();
                cout<<query(root,x,y)<<"\n";
                break;
        }
    }
    return 0;
} 
(5)万能模板(结构体)
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 1 << 30
#define ll long long
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
struct tree{
    ll x;
};
struct SegmentTree{
    tree z[mn << 2];
    ll col[mn << 2];
    inline void update(int rt){
        z[rt].x = z[rt << 1].x + z[rt << 1 | 1].x;
    }
    inline tree operation(tree a,tree b){
        return (tree){a.x + b.x};
    }
    inline void color(int l,int r,int rt,ll v){
        z[rt].x += (r - l + 1) * v;
        col[rt] += v;
    }
    inline void push_col(int l,int r,int rt){
        if(col[rt]){
            int m = (l + r) >> 1;
            color(lson, col[rt]);color(rson, col[rt]);
            col[rt] = 0;
        }
    }
    inline void build(int l,int r,int rt){
        if(l==r){z[rt].x = read();return;}
        int m = (l + r) >> 1;build(lson);build(rson); update(rt);
    }
    inline void modify(int l,int r,int rt,int nowl,int nowr,ll v){
        if(nowl<=l && r<=nowr){color(bson, v); return;}
        int m = (l + r) >> 1; push_col(bson);
        if(nowl<=m) modify(lson, nowl, nowr, v);
        if(m<nowr)  modify(rson, nowl, nowr, v);
        update(rt);
    }
    inline tree query(int l,int r,int rt,int nowl,int nowr){
        if(nowl<=l && r<=nowr) return z[rt];
        int m = (l + r) >> 1; push_col(bson);
        if(nowl<=m){
            if(m<nowr) return operation(query(lson, nowl, nowr), query(rson, nowl, nowr));
            else       return query(lson, nowl, nowr);
        }else          return query(rson, nowl, nowr);
    }
} tr;
int n, m;
int main(){
    n = read(), m = read();
    tr.build(root);
    go(i,1,m,1){
        int s = read(), x = read(), y = read();
        if(s==1){
            ll v = read();
            tr.modify(root, x, y, v);
        }else{
            cout << tr.query(root, x, y).x << "\n";
        }
    }
#define _ 0
    return ~~(0 ^ _ ^ 0);
}

ex:线段树优化Dijkstra

P4779 【模板】单源最短路径(标准版)——AC代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define ll long long
#define mn 100010
#define mm 200010
#define inf 1 << 30
inline int read() {
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int minn[mn << 2], pos[mn << 2], M, n, m;
inline void update(int rt) {
    minn[rt] = min(minn[rt << 1], minn[rt << 1 | 1]);
    pos[rt] = (minn[rt << 1] < minn[rt << 1 | 1]) ? pos[rt << 1] : pos[rt << 1 | 1];
}
inline void build() {
    for(M = 1; M < n + 2; M <<= 1) ;
    go(i, M, (M << 1) - 1, 1) minn[i] = inf, pos[i] = i - M;
    fo(i, M, 1, 1) update(i);
}
inline void modify(int rt, int v) {
    for(minn[rt += M] = v, rt >>= 1; rt; rt >>= 1) update(rt);
}
struct edge{ int v, nxt, w; } e[mm << 1]; int h[mn], p;
inline void add(int a, int b, int c) { e[++p].nxt = h[a], h[a] = p, e[p].v = b, e[p].w = c; }
int dis[mn];
inline void Dij(int s) {
    go(i, 1, n, 1) dis[i] = inf;
    dis[s] = 0, build(), modify(s, 0);
    while(minn[1] < inf) {
        int x = pos[1], d = minn[1]; modify(x, inf);
        if(d != dis[x]) continue;
        rep(i, x) {
            int v = e[i].v, w = e[i].w;
            if(dis[v] > dis[x] + w)
                dis[v] = dis[x] + w, modify(v, dis[v]);
        }
    }
}
int main() {
    n = read(), m = read(); int s = read();
    go(i, 1, m, 1) {
        int a = read(), b = read(), c = read();
        add(a, b, c);
    }
    Dij(s);
    go(i, 1, n, 1) printf("%d ", dis[i]);
    return 0;
}

3.(ex_线段树)zkw线段树

P3374 【模板】树状数组 1 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 500010
#define inf 1<<30
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll z[mn<<2];
int n,m,M;
inline void update(int rt){
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
inline void build(){
    for(M=1;M<n;M<<=1);
    for(int i=M+1;i<=M+n;i++)z[i]=read();
    for(int i=M-1;i;i--)    update(i);
}
inline ll query(int l,int r){
    ll ans=0;
    for(--l += M,++r +=M;l^r^1;l>>=1,r>>=1){
        if(~l&1)ans+=z[l^1];
        if(r&1) ans+=z[r^1];
    }
    return ans;
}
inline void modify(int rt,ll v){
    for(z[rt+=M]+=v,rt>>=1;rt;rt>>=1)update(rt);
}
int main(){
    n=read(),m=read();
    build();
    go(i,1,m,1){
        int s=read();
        if(s==1){
            int x=read();ll v=read();
            modify(x,v);
        }else if(s==2){
            int x=read(),y=read();
            cout<<query(x,y)<<"\n";
        }
    }
    return 0;
}

4.树状数组

(1)P3374 树状数组 1 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 500010
#define inf 1<<30
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll y[mn];
int n,m;
inline ll lb(int x){
    return x&-x;
}
inline void modify(int p,ll v){
    for(;p<=n;p+=lb(p))
        y[p]+=v;
}
inline ll query(int p){
    int ans=0;
    for(;p;p-=lb(p))
        ans+=y[p];
    return ans;
}
int main(){
    n=read();
    m=read();
    go(i,1,n,1){
        int a=read();
        modify(i,a);
    }
    go(i,1,m,1){
        int s=read();
        if(s==1){
            int p=read();ll v=read();
            modify(p,v);
        }else{
            int l=read(),r=read();
            cout<<query(r)-query(l-1)<<"\n";
        }
    }
    return 0;
}
(2)P3368 【模板】树状数组 2 ——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 500010
#define inf 1<<30
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
ll y[mn];
int n,m;
inline ll lb(int x){
    return x&-x;
}
inline void modify(int p,ll v){
    for(;p<=n;p+=lb(p))
        y[p]+=v;
}
inline ll query(int p){
    int ans=0;
    for(;p;p-=lb(p))
        ans+=y[p];
    return ans;
}
int main(){
    n=read();
    m=read();
    ll last=0,now;
    go(i,1,n,1){
        now=read();
        modify(i,now-last);
        last=now;
    }
    go(i,1,m,1){
        int s=read();
        if(s==1){
            int x=read(),y=read();ll v=read();
            modify(x,v);
            modify(y+1,-v);
        }else{
            int x=read();
            cout<<query(x)<<"\n";
        }
    }
    return 0;
}

5.LCA(最近公共祖先)

(1)倍增版
P3379 【模板】最近公共祖先(LCA)——AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 1000100
#define inf 1<<30
#define ll long long
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
#define mk 21
struct node{
    int v,next;
} e[mn*2];
int p=1,h[mn];
inline void add(int a,int b){
    e[p].next=h[a];
    e[p].v=b;
    h[a]=p++;
}
int n,m,s;
int deep[mn];
int fa[mn][mk];

void dfs(int u,int f){
    deep[u]=deep[f]+1;
    fa[u][0]=f;
    for(register int i=1;(1<<i)<=deep[u];i++){
        fa[u][i]=fa[fa[u][i-1]][i-1];
  //      cout<<fa[u][i]<<" ";
    }
//  cout<<"\n";
    rep(i,u){
        int v=e[i].v;
        if(v!=f)    dfs(v,u);
    }
}
int lca(int a,int b){
    if(deep[a]>deep[b]) swap(a,b);
    fo(i,mk-1,0,1)
        if(deep[a]<=deep[b]-(1<<i))
            b=fa[b][i];
//  if(d[a]<=d[b]-(1<<i))
//          b=p[b][i];
    if(a==b)
        return a;
    fo(i,mk-1,0,1){
        if(fa[a][i]==fa[b][i])  continue;
        else    a=fa[a][i],b=fa[b][i];
    }
    return fa[a][0];
}
int main(){
    n=read(),m=read(),s=read();
    go(i,1,n-1,1){
        int u=read(),v=read();
        add(u,v);
        add(v,u);
    }
    dfs(s,0);
    go(i,1,m,1){
        int a=read(),b=read();
        cout<<lca(a,b)<<"\n";
    }
    return 0;
}
(2)树链剖分版
P3379 【模板】最近公共祖先(LCA)——AC代码
#include <iostream>
#include <cstdio>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 500010
#define inf 1 << 30
#define ll long long
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘) { if(ch == ‘-‘) f = -f; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
    return x * f;
}
struct edge{
    int v, nxt;
}e[mn << 1];
int h[mn], p;
inline void add(int a, int b) {
    e[++p].nxt = h[a], h[a] = p, e[p].v = b;
}
int dep[mn], top[mn], sze[mn], fa[mn], son[mn], n, m;
void dfs1(int x, int f, int deep) {
    dep[x] = deep;
    sze[x] = 1;
    fa[x] = f;
    int maxson = -1;
    rep(i, x) {
        int v = e[i].v;
        if(v == f) continue;
        dfs1(v, x, deep + 1);
        sze[x] += sze[v];
        if(maxson < sze[v]) maxson = sze[v], son[x] = v;
    }
}
void dfs2(int x, int topf) {
    top[x] = topf;
    if(!son[x]) return;
    dfs2(son[x], topf);
    rep(i, x) {
        int v = e[i].v;
        if(v == fa[x] || v == son[x]) continue;
        dfs2(v, v);
    }
}
inline int LCA(int x, int y) {
    while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    return dep[x] < dep[y] ? x : y;
}
int main() {
    n = read(), m = read();
    int rot = read();
    go(i, 1, n - 1, 1) {
        int a = read(), b = read();
        add(a, b), add(b, a);
    }
    dfs1(rot, 0, 1);
    dfs2(rot, rot);
    go(i, 1, m, 1) {
        int x = read(), y = read();
        printf("%d\n", LCA(x, y));
    }
    return 0;
}

6.平衡树

(1)Treap

P3369 普通平衡树——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define mn 100010
#define inf 1 << 30
#define ll long long
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
inline void write(int x){
    if (x < 0)putchar(‘-‘),x = -x;
    if (x > 9)write(x / 10);
    putchar(x % 10 + ‘0‘);
}
//This is AC head above...
int rt, tot;
struct tree{
    int size, ch[2], w, pos;
};
struct Treap{
    tree z[mn];
    inline void update(int rt){
        z[rt].size = z[z[rt].ch[0]].size + z[z[rt].ch[1]].size + 1;
    }
    inline void rotate(int &rt,int p){
        int t = z[rt].ch[p];
        z[rt].ch[p] = z[t].ch[p ^ 1], z[t].ch[p ^ 1] = rt;
        update(rt), update(t);
        rt = t;
    }
    inline void add(int x,int &rt){
        if(!rt){
            rt = ++tot, z[rt].size = 1, z[rt].w = x, z[rt].pos = rand();
            return;
        }
        z[rt].size++;
        int nxt = x < z[rt].w ? 0 : 1;
        add(x, z[rt].ch[nxt]);
        if(z[z[rt].ch[nxt]].pos<z[rt].pos)
            rotate(rt, nxt);
    }
    inline void del(int x,int &rt){
        if(z[rt].w==x){
            if(z[rt].ch[0]*z[rt].ch[1]==0){
                rt = z[rt].ch[0] + z[rt].ch[1];
                return;
            }
            if(z[z[rt].ch[0]].pos>z[z[rt].ch[1]].pos){
                rotate(rt, 1);
                del(x, z[rt].ch[0]);
            }else{
                rotate(rt, 0);
                del(x, z[rt].ch[1]);
            }
        }else{
            int nxt = x < z[rt].w ? 0 : 1;
            del(x, z[rt].ch[nxt]);
        }
        update(rt);
    }
    inline int find(int x,int rt){
        if(!rt)
            return 1;
        if(z[rt].w>=x)
            return find(x, z[rt].ch[0]);
        else
            return find(x, z[rt].ch[1]) + z[z[rt].ch[0]].size + 1;
    }
    inline int ask(int x,int rt){
        if(z[z[rt].ch[0]].size==x-1)
            return z[rt].w;
        if(z[z[rt].ch[0]].size>=x)
            return ask(x, z[rt].ch[0]);
        else
            return ask(x - z[z[rt].ch[0]].size - 1, z[rt].ch[1]);
    }
    inline int pre(int x,int rt){
        if(!rt)
            return -inf;
        if(z[rt].w<x)
            return max(z[rt].w, pre(x, z[rt].ch[1]));
        return pre(x, z[rt].ch[0]);
    }
    inline int nxt(int x,int rt){
        if(!rt)
            return inf;
        if(z[rt].w>x)
            return min(z[rt].w, nxt(x, z[rt].ch[0]));
        return nxt(x, z[rt].ch[1]);
    }
} tr;
int m;
int main()
{
    srand((unsigned)time(NULL));
    m = read();
    go(i,1,m,1){
        int s = read(), x = read();
        int ans;
        if(s==1)
            tr.add(x, rt);
        if(s==2)
            tr.del(x, rt);
        if(s==3)
            ans = tr.find(x, rt);
        if(s==4)
            ans = tr.ask(x, rt);
        if(s==5)
            ans = tr.pre(x, rt);
        if(s==6)
            ans = tr.nxt(x, rt);
        if(s>2)
            cout << ans << "\n";
    }
    return 0;
}

(2)Splay

P3369 【模板】普通平衡树——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 500010
#define inf 1 << 30
#define ll long long
#define ld long double
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
//This is AC head above...
int rot, tot, n;
struct tree{
    int ch[2], fa, cnt, w, size;
};
struct Splay{
    tree z[mn];
    void update(int rt){
        z[rt].size = z[z[rt].ch[0]].size + z[z[rt].ch[1]].size + z[rt].cnt;
    }
    void rotate(int a){
        int b = z[a].fa;
        int c = z[b].fa;
        int k = z[b].ch[1] == a;
        z[c].ch[z[c].ch[1] == b] = a;
        z[a].fa = c;
        z[b].ch[k] = z[a].ch[k ^ 1];
        z[z[a].ch[k ^ 1]].fa = b;
        z[a].ch[k ^ 1] = b;
        z[b].fa = a;
        update(b), update(a);
    }
    void splay(int a,int goal){
        while(z[a].fa!=goal){
            int b = z[a].fa;
            int c = z[b].fa;
            if(c!=goal)
                (z[b].ch[0] == a) ^ (z[c].ch[0] == b) ? rotate(a) : rotate(b);
            rotate(a);
        }
        if (goal == 0)
            rot = a;
    }
    void insert(int x){
        int fa = 0, rt = rot;
        while(rt && z[rt].w!=x){
            fa = rt;
            int nxt = x < z[rt].w ? 0 : 1;
            rt = z[rt].ch[nxt];
        }
        if(rt)
            z[rt].cnt++;
        else{
            rt = ++tot;
            int nxt = x < z[fa].w ? 0 : 1;
            if(fa)
                z[fa].ch[nxt] = rt;
            z[tot].ch[0] = 0, z[tot].ch[1] = 0, z[tot].fa = fa;
            z[tot].w = x, z[tot].size = 1, z[tot].cnt = 1;
        }
        splay(rt, 0);
    }
    void find(int x){
        int rt = rot;
        if(!rt)
            return;
        //int nxt = x < z[rt].w ? 0 : 1;
        //while(z[rt].ch[nxt] && x!=z[rt].w)
            //nxt = x < z[rt].w ? 0 : 1, rt = z[rt].ch[nxt];
        while (z[rt].ch[x > z[rt].w] && x != z[rt].w)
            rt = z[rt].ch[x > z[rt].w];
        splay(rt, 0);
    }
    int nxt(int x,int f){
        find(x);
        int rt = rot;
        if((z[rt].w>x && f) || (z[rt].w<x && !f))
            return rt;
        rt = z[rt].ch[f];
        while(z[rt].ch[f^1])
            rt = z[rt].ch[f ^ 1];
        return rt;
    }
    void del(int x){
        int last = nxt(x, 0);
        int next = nxt(x, 1);
        splay(last, 0);
        splay(next, last);
        int t = z[next].ch[0];
        if(z[t].cnt>1){
            z[t].cnt--;
            splay(t, 0);
        }else{
            z[next].ch[0] = 0;
        }
    }
    int ask(int x){
        int rt = rot;
        if(z[rt].size<x)
            return 0;
        while(1119){
            int b = z[rt].ch[0];
            if(x>z[b].size+z[rt].cnt){
                x -= z[b].size + z[rt].cnt;
                rt = z[rt].ch[1];
            }else if(z[b].size>=x)
                rt = b;
            else
                return z[rt].w;
        }
    }
    int findx(int x){
        find(x);
        return z[z[rot].ch[0]].size;
    }
    int query(int x,int f){
        return z[nxt(x, f)].w;
    }
} tr;
int main(){
    tr.insert(-2147483647);
    tr.insert(+2147483647);
    n = read();
    go(i,1,n,1){
        int s = read(), x = read();
        int ans;
        if(s==1)
            tr.insert(x);
        if(s==2)
            tr.del(x);
        if(s==3)
            ans = tr.findx(x);
        if(s==4)
            ans = tr.ask(x+1);
        if(s==5)
            ans = tr.query(x, 0);
        if(s==6)
            ans = tr.query(x, 1);
        if(s>2)
            cout << ans << "\n";
    }
    return 0;
}
P3391 【模板】文艺平衡树(Splay)——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 2147483647
#define ll long long
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
//This is AC head above...
int n, m, rot, tot = 0, a[mn];
struct tree{
    int ch[2], w, sze, fa, col;
    tree(int _w = 0, int _sze = 0, int _fa = 0, int _col = 0)
    : w(_w), sze(_sze), fa(_fa), col(_col) { ch[0] = ch[1] = 0; }
};
struct Splay{
    tree z[mn];
    inline void update(int rt){
        z[rt].sze = z[z[rt].ch[0]].sze + z[z[rt].ch[1]].sze + 1;
    }
    inline void change(int x){ //jiao huan zuo you zi shu
        swap(z[x].ch[0], z[x].ch[1]);
    }
    inline void push_col(int rt){
        if(z[rt].col){
            z[z[rt].ch[0]].col ^= 1;
            z[z[rt].ch[1]].col ^= 1;
            z[rt].col = 0;
            swap(z[rt].ch[0], z[rt].ch[1]);
        }
    }
    inline int iden(int rt){
        return z[z[rt].fa].ch[0] == rt ? 0 : 1;
    }
    inline void connect(int x,int y,int son){
        z[x].fa = y;
        z[y].ch[son] = x;
    }
    inline void rotate(int x){
        int y = z[x].fa;
        int moot = z[y].fa;
        int yson = iden(x);
        int mootson = iden(y);
        int B = z[x].ch[yson ^ 1];
        connect(B, y, yson), connect(y, x, yson ^ 1), connect(x, moot, mootson);
        update(y), update(x);
    }
    inline void splay(int x,int &k){
        if(x==k)
            return;
        int p = z[k].fa;
        while(z[x].fa != p){
            push_col(x);      //warning
            int y = z[x].fa;
            if(z[y].fa != p)  //warning
                rotate(iden(x) ^ iden(y) ? x : y);
            rotate(x);
        }
        k = x;
    }
    inline int findkth(int rt,int k){
        while(1119){
            push_col(rt);
            if(z[rt].ch[0] && k <= z[z[rt].ch[0]].sze){
                rt = z[rt].ch[0]/*,puts("okok")*/;
            }else {
                if(z[rt].ch[0])
                    k -= z[z[rt].ch[0]].sze;
                if(!--k)
                    return rt;
                rt = z[rt].ch[1];
            }
        }
    }
    inline int getRange(int l,int r,int &rt){
        int x = findkth(rt, l);
        //puts("getxok");
        splay(x, rt);
        //cout << rot << "\n";
        int y = findkth(rt, r + 2);
        int ooo = z[rt].ch[1];
        splay(y, ooo);
        return z[y].ch[0];
    }
    inline void modify(int &rt,int nowl,int nowr){
        int x = getRange(nowl, nowr, rt);
        z[x].col ^= 1;
        update(z[rt].ch[1]), update(rt);
    }
    inline void build(int l,int r,int rt){
        int m = (l + r) >> 1;
        z[rt].w = a[m];
        if(l <= m - 1) {
            z[z[rt].ch[0] = ++tot].fa = rt;
            build(l, m - 1, z[rt].ch[0]);
        }
        if(m + 1 <= r) {
            z[z[rt].ch[1] = ++tot].fa = rt;
            build(m + 1, r, z[rt].ch[1]);
        }
        update(rt);
    }
    inline void dfs(int rt){
        if(rt == 0)
            return;
        push_col(rt);
        //puts("push_colok");
        dfs(z[rt].ch[0]);
        if(z[rt].w > 0)
            printf("%d ", z[rt].w);
        dfs(z[rt].ch[1]);
    }
} tr;
int main(){
    n = read(), m = read();
    go(i, 1, n, 1) a[i] = i;
    rot = ++tot;
    tr.build(0, n + 1, rot);
    go(i,1,m,1){
        int x = read(), y = read();
        tr.modify(rot, x, y);
    }
    tr.dfs(rot);
    return 0;
}
(3)FHQ Treap
P3369 【模板】普通平衡树——AC代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 100010
#define inf 1 << 30
#define ll long long
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘) { if(ch == ‘-‘) f = -f; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
    return x * f;
}
struct tree {
    int ch[2], w, pri, sze;
} z[mn];
int cnt;
inline void update(int rt) {
    z[rt].sze = 1;
    if(z[rt].ch[0])
        z[rt].sze += z[z[rt].ch[0]].sze;
    if(z[rt].ch[1])
        z[rt].sze += z[z[rt].ch[1]].sze;
}
inline int newnode(int w = 0) {
    z[++cnt].sze = 1;
    z[cnt].w = w;
    z[cnt].pri = rand();
    return cnt;
}
inline int merge(int x, int y) {
    if(!x || !y) return x + y;
    if(z[x].pri < z[y].pri) {
        z[x].ch[1] = merge(z[x].ch[1], y);
        update(x);
        return x;
    } else {
        z[y].ch[0] = merge(x, z[y].ch[0]);
        update(y);
        return y;
    }
}
inline void split(int rt, int k, int &x, int &y) {
    if(!rt) x = y = 0;
    else  {
        if(z[rt].w <= k) {
            x = rt, split(z[rt].ch[1], k, z[rt].ch[1], y);
        } else {
            y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);
        }
        update(rt);
    }
}
inline int findkth(int rt, int k) {
    while(1119) {
        if(k <= z[z[rt].ch[0]].sze)
            rt = z[rt].ch[0];
        else if(k == z[z[rt].ch[0]].sze + 1){
            return rt;
        } else {
            k -= z[z[rt].ch[0]].sze + 1, rt = z[rt].ch[1];
        }
    }
}
int n, rot, x, y;
inline void debug() {
    go(i, 1, cnt, 1) {
        printf("%d:%d %d %d\n", i, z[i].pri, z[i].sze, z[i].w);
    }
}
int main() {
    srand((unsigned)time(NULL));
    n = read();
    int zz;
    go(i, 1, n, 1) {
        int s = read(), a = read();
        if(s == 1) {
            split(rot, a, x, y);
            rot = merge(merge(x, newnode(a)), y);
        }
        if(s == 2) {
            split(rot, a, x, zz);
            split(x, a - 1, x, y);
            y = merge(z[y].ch[0], z[y].ch[1]);
            rot = merge(merge(x, y), zz);
        }
        if(s == 3) {
            split(rot, a - 1, x, y);
            printf("%d\n", z[x].sze + 1);
            rot = merge(x, y);
        }
        if(s == 4) {
            printf("%d\n", z[findkth(rot, a)].w);
        }
        if(s == 5) {
            split(rot, a - 1, x, y);
            printf("%d\n", z[findkth(x, z[x].sze)].w);
            rot = merge(x, y);
        }
        if(s == 6) {
            split(rot, a, x, y);
            printf("%d\n", z[findkth(y, 1)].w);
            rot = merge(x, y);
        }
//        cout << x << " " << y << " " << zz << " " << rot << "\n";
//        debug();
    }
    return 0;
}
维护区间操作
P3372 【模板】线段树1 ——AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
using namespace std;
#define go(i,j,n,k) for(int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(int i=j;i>=n;i-=k)
#define rep(i,x) for(int i=h[x];i;i=e[i].nxt)
#define mn 100010
#define ll long long
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline void fre() {
    freopen(".in", "r", stdin);
    freopen(".out", "w", stdout);
}
struct tree {
    int sze, ch[2], pri, w;
    ll x, sum, col;
} z[mn];
inline void update(int rt) {
    z[rt].sze = 1, z[rt].sum = z[rt].x;
    if(z[rt].ch[0])
        z[rt].sze += z[z[rt].ch[0]].sze, z[rt].sum += z[z[rt].ch[0]].sum;
    if(z[rt].ch[1])
        z[rt].sze += z[z[rt].ch[1]].sze, z[rt].sum += z[z[rt].ch[1]].sum;
}
inline void push_col(int rt) {
    if(z[rt].col) {
        z[z[rt].ch[0]].x += z[rt].col;
        z[z[rt].ch[1]].x += z[rt].col;
        z[z[rt].ch[0]].col += z[rt].col;
        z[z[rt].ch[1]].col += z[rt].col;
        z[z[rt].ch[0]].sum += z[rt].col * z[z[rt].ch[0]].sze;
        z[z[rt].ch[1]].sum += z[rt].col * z[z[rt].ch[1]].sze;
        z[rt].col = 0;
    }
}
int cnt;
inline int newnode(int w, int v = 0) {
    z[++cnt].x = v;
    z[cnt].w = w;
    z[cnt].sze = 1;
    z[cnt].sum = v;
    z[cnt].pri = rand();
    return cnt;
}
inline int merge(int x, int y) {
    if(!x || !y) return x + y;
    if(z[x].pri < z[y].pri) {
        push_col(x);
        z[x].ch[1] = merge(z[x].ch[1], y);
        update(x);
        return x;
    } else {
        push_col(y);
        z[y].ch[0] = merge(x, z[y].ch[0]);
        update(y);
        return y;
    }
}
inline void split(int rt, int k, int &x, int &y) {
    if(!rt) x = y = 0;
    else {
        push_col(rt);
        if(z[rt].w <= k) {
            x = rt, split(z[rt].ch[1], k, z[rt].ch[1], y);
        } else {
            y = rt, split(z[rt].ch[0], k, x, z[rt].ch[0]);
        }
        update(rt);
    }
}
int n, m;
int xx, yy, rot, zz;
int main(){
//  fre();
    n = read(), m = read();
    go(i, 1, n, 1) {
        int a = read();
        split(rot, i, xx, yy);
        rot = merge(merge(xx, newnode(i, a)), yy);
    }
    go(i, 1, m, 1) {
        int s = read(), x = read(), y = read();
        if(s == 1) {
            ll v = read();
            split(rot, y, xx, zz);
            split(xx, x - 1, xx, yy);
            z[yy].col += v;
            z[yy].x += v;
            z[yy].sum += z[yy].sze * v;
            rot = merge(merge(xx, yy), zz);
        } else {
            split(rot, y, xx, zz);
            split(xx, x - 1, xx, yy);
            printf("%lld\n", z[yy].sum);
            rot = merge(merge(xx, yy), zz);
        }
    }
    return 0;
}

7.权值线段树

P1908 逆序对——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 500200
#define inf 2147483647
#define ll long long
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
//This is AC head above...
ll z[mn<<2];
inline void update(int rt){
    z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
inline void build(int l,int r,int rt){
    if(l==r){
        z[rt] = 0;
        return;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    update(rt);
}
inline void modify(int l,int r,int rt,ll x){
    if(l==r){
        z[rt]++;
        return;
    }
    int m = (l + r) >> 1;
    if(x<=m)
        modify(lson, x);
    else
        modify(rson, x);
    update(rt);
}
inline ll query(int l,int r,int rt,int nowl,int nowr){
    if(nowl<=l && r<=nowr){
        return z[rt];
    }
    int m = (l + r) >> 1;
    if(nowl<=m){
        if(m<nowr)
            return query(lson, nowl, nowr) + query(rson, nowl, nowr);
        else
            return query(lson, nowl, nowr);
    }else{
        return query(rson, nowl, nowr);
    }
}
int a[mn], b[mn], n, m;
int main(){
    n = read();
    go(i, 1, n, 1) a[i] = b[i] = read();
    sort(b + 1, b + n + 1);
    int size = unique(b + 1, b + n + 1) - b - 1;
    go(i, 1, n, 1) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
    build(1, 500000, 1);
    ll ans = 0;
    go(i, 1, n, 1) {
        ans += query(root, a[i] + 1, 500000);
        modify(root, a[i]);
    }
    cout << ans << "\n";
    return 0;
}

8.主席树(可持久化(权值)线段树)

P3834 【模板】可持久化线段树1(主席树)——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 200020
#define inf 2147483647
#define ll long long
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
//This is AC head above...
int n, q, m, cnt = 0;
int a[mn], b[mn];
int rot[mn];
struct node{
    int l, r, sum;
    explicit node(int _l = 0, int _r = 0, int _sum = 0)
        : l(_l), r(_r), sum(_sum) {}
} z[mn << 5];
inline int build(int l,int r){
    int rt = ++cnt;
    z[rt].sum = 0;
    int m = (l + r) >> 1;
    if (l < r)
        z[rt].l = build(l, m),
        z[rt].r = build(m + 1, r);
    return rt;
}
inline int modify(int l,int r,int pre,int x){
    int rt = ++cnt;
    z[rt].l = z[pre].l, z[rt].r = z[pre].r, z[rt].sum = z[pre].sum + 1;
    int m = (l + r) >> 1;
    if (l < r) {
        if (x <= m)
            z[rt].l = modify(l, m, z[pre].l, x);
        else
            z[rt].r = modify(m + 1, r, z[pre].r, x);
    }
    return rt;
}
inline int query(int l,int r,int k,int nowl,int nowr){
    if(l>=r) return l;
    int x = z[z[nowr].l].sum - z[z[nowl].l].sum;
    int m = (l + r) >> 1;
    if(x >= k) return query(l, m, k, z[nowl].l, z[nowr].l);
    else       return query(m + 1, r, k - x, z[nowl].r, z[nowr].r);
}
int main(){
    n = read(), q = read();
    go(i, 1, n, 1) a[i] = b[i] = read();
    sort(b + 1, b + n + 1);
    m = unique(b + 1, b + n + 1) - b - 1;
    rot[0] = build(1, m);
    go(i, 1, n, 1)
        rot[i] = modify(1, m, rot[i - 1], lower_bound(b + 1, b + m + 1, a[i]) - b);
    go(i, 1, q, 1) {
        int x = read(), y = read(), z = read();
        cout << b[query(1, m, z, rot[x - 1], rot[y])] << "\n";
    }
    return 0;
}

9.可持久化数组(可持久化线段树)

P3919 【模板】可持久化数组(可持久化线段树/平衡树)——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define mn 1000010
#define inf 2147483647
#define ll long long
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
//This is AC head above...
struct tree{
    int l, r, w;
};
int a[mn], rot[mn];
struct PersistableSegmentTree{
    tree z[mn << 5];
    int cnt = 0;
    inline void build(int l,int r,int &rt){
        rt = ++cnt;
        if(l==r){
            z[rt].w = a[l];
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, z[rt].l);
        build(m + 1, r, z[rt].r);
    }
    inline void modify(int l,int r,int &rt,int pre,int now,int v){
        rt = ++cnt;
        z[rt].l = z[pre].l, z[rt].r = z[pre].r, z[rt].w = z[pre].w;
        if(l==r){
            z[rt].w = v;
            return;
        }
        int m = (l + r) >> 1;
        if(now<=m)
            modify(l, m, z[rt].l, z[pre].l, now, v);
        else
            modify(m + 1, r, z[rt].r, z[pre].r, now, v);
    }
    inline int query(int l,int r,int rt,int now){
        if(l==r)
            return z[rt].w;
        int m = (l + r) >> 1;
        if(now<=m)
            return query(l, m, z[rt].l, now);
        else
            return query(m + 1, r, z[rt].r, now);
    }
} P_tr;
int n, m;
int main(){
    n = read(), m = read();
    go(i, 1, n, 1) a[i] = read();
    P_tr.build(1, n, rot[0]);
    go(i, 1, m, 1){
        int pre = read(), s = read(), x = read();
        if(s==1){
            int v = read();
            P_tr.modify(1, n, rot[i], rot[pre], x, v);
        }else{
            cout << P_tr.query(1, n, rot[pre], x) << "\n";
            rot[i] = rot[pre];
        }
    }
    return 0;
}

10.二维树状数组

(1)单点修改,区间求和
#include <iostream>
#include <cstdio>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define rep(i, x) for(int i = h[x]; i; i = e[i].nxt)
#define mn 2010
#define inf 1 << 30
#define ll long long
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘) { if(ch == ‘-‘) f = -f; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
    return x * f;
}
ll z[mn][mn], n, m, q;
inline int lb(int x) { return x & -x; }
inline void modify(int x, int y, ll v) {
    for(int i = x; i <= n; i += lb(i))
        for(int j = y; j <= m; j += lb(j))
            z[i][j] += v;
}
inline ll query(int x, int y) {
    ll ans = 0;
    for(int i = x; i; i -= lb(i))
        for(int j = y; j; j -= lb(j))
            ans += z[i][j];
    return ans;
}
int main() {
    n = read(), m = read(), q = read();
    go(i, 1, n, 1) go(j, 1, m, 1){
        ll x = read(); modify(i, j, x);
    }
    go(i, 1, q, 1) {
        int s = read(), x = read(), y = read();
        if(s == 1) {
            ll v = read();
            modify(x, y, v);
        } else if(s == 2){
            int xx = read(), yy = read();
            printf("%lld\n", query(xx, yy) - query(x - 1, yy) - query(xx, y - 1) + query(x - 1, y - 1));
        }
    }
    return 0;
}

11.扫描线

POJ 1151 Atlantis——AC代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
#define fo(i, j, n, k) for(int i = j; i >= n; i -= k)
#define inf 1 << 30
#define mn 100010
#define ll long long
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘) { if(ch == ‘-‘) f = -f; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
    return x * f;
}
struct tree{
    int mark; double sum;
} z[mn << 2];
struct seg{
    double l, r, h;
    int d;
    seg() {}
    seg(double _l, double _r, double _h, int _d) : l(_l), r(_r), h(_h), d(_d) {}
    bool operator < (const seg &b) const { return h < b.h; }
} s[mn];
int n, num, kkk;
double ha[mn];
double x, y, xx, yy;
#define root 0, m - 1, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline void update(int l, int r, int rt) {
    if(z[rt].mark) z[rt].sum = ha[r + 1] - ha[l];
    else if(l == r) z[rt].sum = 0;
    else z[rt].sum = z[rt << 1].sum + z[rt << 1 | 1].sum;
}
inline void modify(int l, int r, int rt, int nowl, int nowr, int d) {
    if(nowl <= l && r <= nowr) {
        z[rt].mark += d;
        update(bson);
        return;
    }
    int m = (l + r) >> 1;
    if(nowl <= m) modify(lson, nowl, nowr, d);
    if(m < nowr)  modify(rson, nowl, nowr, d);
    update(bson);
}
inline int search(double key, double* x, int n) {
    int l = 0, r = n - 1;
    while(l <= r) {
        int m = (l + r) >> 1;
        if(x[m] == key) return m;
        if(x[m] > key) r = m - 1;
        else l = m + 1;
    }
    return -1;
}
int main() {
    while(cin >> n, n) {
        num = 0;
        go(i, 0, n - 1, 1) {
            cin >> x >> y >> xx >> yy;
            ha[num] = x;
            s[num++] = seg(x, xx, y, 1);
            ha[num] = xx;
            s[num++] = seg(x, xx, yy, -1);
        }
        sort(ha, ha + num);
        sort(s, s + num);
        int m = 1;
        go(i, 1, num - 1, 1)
            if(ha[i] != ha[i - 1]) ha[m++] = ha[i];
        double ans = 0;
        go(i, 0, num - 1, 1) {
            int L = search(s[i].l, ha, m);
            int R = search(s[i].r, ha, m) - 1;
            modify(root, L, R, s[i].d);
            ans += z[1].sum * (s[i + 1].h - s[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n", ++kkk, ans);
    }
    return 0;
}

四.其他

(一)字符串算法

1.manacher算法

P3805 【模板】manacher算法——AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 26000100
#define inf 1<<30
#define ll long long
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
char s[mn],str[mn];
int f[mn],l;
inline void manacher(){
    int nowmid=0,nowr;
    for(int i=l;str[i]!=0;i++)
        str[i]=0;
    go(i,1,l-1,1){
        if(nowmid>i){
            f[i]=min(f[nowr*2-i],f[nowr]+nowr-i);
        //  cout<<"*"<<" ";
        }
        else    f[i]=1;
        while(str[i+f[i]]==str[i-f[i]])
            ++f[i];
    //  for (;str[i+f[i]]==str[i-f[i]];++f[i]);
        if(i+f[i]>nowmid){
            nowmid=i+f[i];
            nowr=i;
    //      cout<<i<<"\n";
        }
    }
}
inline void init(char a){
    //a=‘#‘;
    str[0]=a,str[1]=a;
    go(i,0,l-1,1){
        str[(i<<1)+2]=s[i];
        str[(i<<1)+3]=a;
    }
    l=(l<<1)+2;
    str[l]=0;
}
inline char huaji(){
    srand((unsigned)time(NULL));
    int o=rand()%120;
    while((o>=‘a‘ && o<=‘z‘ )||(o>=7 && o<=10))
        o=rand()%120;
    return char(o);
}
int main(){
    scanf("%s",s);
    l=strlen(s);
//  cout<<l<<"\n";
    char a=huaji();
    init(a);
//  printf("%s %s\n",s,str);
    manacher();
    int ans=-1;
    go(i,0,l-1,1)
        ans=max(f[i],ans);
    cout<<ans-1;
    return 0;
}

2.Trie树

struct node{
    int next[26];
    bool exist;
    node(){exist=false;memset(next,0,sizeof(next));}
} z[233333];
int cnt=1;
inline void insert(char *s){
    int l=strlen(s+1);
    int p=root;
    go(i,1,l,1){
        if(z[p].next[s[i]-‘a‘]==0){
            cnt++;
            z[p].next[s[i]-‘a‘]=cnt;
        }
        p=z[p].next[s[i]-‘a‘];
    }
    z[p].exist=true;
}
inline bool query(char *s){
    int l=strlen(s+1);
    int p=root;
    go(i,1,l,1){
        if(z[p].next[s[i]-‘a‘]==0)
            return false;
        p=z[p].next[s[i]-‘a‘];
    }
    return z[p].exist;
}

3.字符串hash

(1)自然溢出法:P3370 【模板】字符转哈希——AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 10010
#define ms 1550
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define base 12581
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
char s[ms];
int n,sum;
ull h[ms],bit[ms];
ull a[mn],t;
int main(){
    n=read();
    bit[0]=1;
    go(i,1,ms-30,1){
        bit[i]=bit[i-1]*base;
    }
    //采用自然炸裂法(逃
    go(x,1,n,1){
        scanf("%s",s);
        ull l=strlen(s);
        go(i,0,l-1,1){
            h[i+1]=h[i]*base+s[i];
        }
        a[x]=h[l];
    }
    sort(a+1,a+n+1);
    go(i,1,n,1){
        if(t!=a[i])
            sum++;
        t=a[i];
    }
    cout<<sum<<"\n";
    return 0;
}
(2)单模哈希法:P3370 【模板】字符转哈希——80分代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define rep(i,x) for(register int i=h[x];i;i=next[i])
#define mn 10010
#define ms 1550
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define base 12581
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
char s[ms];
const ull p=19260817;
int n,sum;
ull h[ms],bit[ms];
ull a[mn],t;
int main(){
    n=read();
    bit[0]=1;
    go(i,1,ms-30,1){
        bit[i]=(bit[i-1]*base)%p;
    }
    //采用dan膜炸裂法(逃
    go(x,1,n,1){
        scanf("%s",s);
        ull l=strlen(s);
        go(i,0,l-1,1){
            h[i+1]=(h[i]*base+s[i])%p;
        }
        a[x]=h[l];
    }
    sort(a+1,a+n+1);
    go(i,1,n,1){
        if(t!=a[i])
            sum++;
        t=a[i];
    }
    cout<<sum<<"\n";
    return 0;
}
(3)双模哈希法:P3370 【模板】字符转哈希——AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 10010
#define ms 1550
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define mod1 19260817
#define mod2 19660813
#define base 12581
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct node
{
    ull x,y;
}a[mn];
char s[mn];
int n,ans=1;
inline bool cmp(node a,node b){
    return a.x<b.x;
}
inline ull hash1(char s[]){
    int len=strlen(s);
    ull ans=0;
    for (int i=0;i<len;i++)
        ans=(ans*base+(ull)s[i])%mod1;
    return ans;
}
inline ull hash2(char s[]){
    int len=strlen(s);
    ull ans=0;
    for (int i=0;i<len;i++)
        ans=(ans*base+(ull)s[i])%mod2;
    return ans;
}

int main(){
    n=read();
    for (int i=1;i<=n;i++){
        scanf("%s",s);
        a[i].x=hash1(s);
        a[i].y=hash2(s);
    }
    sort(a+1,a+n+1,cmp);
    for (int i=2;i<=n;i++)
        if (a[i].x!=a[i-1].x || a[i-1].y!=a[i].y)
            ans++;
    cout<<ans;
}

4.KMP字符串匹配

POJ 3461 乌力波————AC代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(int i=j;i>=n;i-=k)
#define rep(i,x) for(int i=h[x];i;i=e[i].nxt)
#define mn 1000100
#define inf 1<<30
#define ll long long
inline ll read(){int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
                while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
// AC head...

struct KMP{
    int ne[mn], len;
    inline void get_ne(char ch[]){
        memset(ne, 0, sizeof 0);
        ne[0] = ne[1] = 0;
        len = strlen(ch);
        go(i,1,len-1,1){
            int x = ne[i];
            while(x && ch[i] != ch[x])
                x = ne[x];
            ne[i + 1] = ch[i] == ch[x] ? x + 1 : 0;
        }
    }
    inline int finds(char ch[], char s[]){
        int x = 0, ans = 0;
        for(int i = 0; s[i]; i++){
            while(x && ch[x] != s[i])
                x = ne[x];
            if(ch[x] == s[i])
                x++;
            if(x == len)
                ans++;
        }
        return ans;
    }
    inline void debug(){//附赠debug
        go(i, 1, len, 1)
            printf("ne[%d] = %d\n", i, ne[i]);
    }
} worker;
char ch[mn], s[mn];
int T;
inline void init() {
    memset(ch, 0, sizeof ch);
    memset(s, 0, sizeof s);
}
int main(){
    //freopen("oulipo.in", "r", stdin);
    //freopen("oulipo.out", "w", stdout);
    T = read();
    while(T--) {
        init();
        scanf("%s%s", ch, s);
        worker.get_ne(ch);
        printf("%d\n", worker.finds(ch, s));
    }
    return 0;
}
P3375 【模板】KMP字符串匹配 ————AC代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define go(i,j,n,k) for(int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(int i=j;i>=n;i-=k)
#define mn 1000100
#define inf 1<<30
#define ll long long
inline ll read(){int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
                while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
// AC head...

struct KMP{
    int len, ne[mn];
    inline void get_ne(char ch[]) {
        memset(ne, 0, sizeof ne);
        ne[0] = ne[1] = 0;
        len = strlen(ch);
        go(i, 1, len - 1, 1) {
            int x = ne[i];
            while(x && ch[i] != ch[x])
                x = ne[x];
            ne[i + 1] = ch[i] == ch[x] ? x + 1 : 0;
        }
    }
    inline int finds(char ch[], char s[]) {
        int x = 0, ans = 0;
        for(int i = 0; s[i]; i++){
            while(x && ch[x] != s[i])
                x = ne[x];
            if(ch[x] == s[i])
                x++;
            if(x == len)
                printf("%d\n", i - len + 2), ans++;
        }
        return ans;
    }
    inline void output() {
        go(i, 1, len, 1)
            printf("%d ", ne[i]);
        puts("");
    }
} kmp;
char ch[mn], s[mn];
int main() {
    scanf("%s%s", s, ch);
    kmp.get_ne(ch);
    int ans = kmp.finds(ch, s);
    kmp.output();
    int _ = 0;
    return ~~(0^_^0);
}

(二)排序算法(暂且不在数论里)

1.归并排序

P1177 【模板】快速排序——AC代码
#include<bits/stdc++.h>
using namespace std;
#define for(i,j,n,k) for(int i=j;i<=n;i+=k)
#define mn 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘ or ch<‘0‘){if(ch==‘-‘) f=-1;ch=getchar();}
    while(ch>=‘0‘ and ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int a[mn],by[mn];
inline void msort(int *A,int x,int y,int *T){
    if(y-x>1){
        int m=x+(y-x)/2;
        int p=x,q=m,i=x;
        msort(A,x,m,T);
        msort(A,m,y,T);
        while(p<m||q<y){
            if(q>=y||(p<m&&A[p]<=A[q]))
                T[i++]=A[p++];
            else
                T[i++]=A[q++];
        }
        for(i,x,y-1,1){
            A[i]=T[i];
        }
    }
}
int n;
int main(){
    n=read();
    for(i,1,n,1){
        a[i]=read();
    }
    msort(a,1,n+1,by);
    for(i,1,n,1){
        cout<<a[i]<<‘ ‘;
    }
    return 0;
}

2.快速排序

P1177 【模板】快速排序——AC代码
#include<iostream>
using namespace std;
int n,a[100005];
int qsort(int l,int r)
{
    int i,j,mid,p;
    i=l;j=r;
    mid=a[(l+r)/2];
    do
    {
        while(a[i]<mid)i++;
        while(a[j]>mid)j--;
        if(i<=j){
            p=a[i];a[i]=a[j];a[j]=p;
            i++;j--;
        }
    }while(i<=j);
    if(l<j)qsort(l,j);
    if(i<r)qsort(i,r);
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    qsort(1,n);
    for(int i=1;i<=n;i++){
        cout<<a[i]<<" ";
    }
    return 0;
} 

3.堆排序

P1177 【模板】快速排序——AC代码
#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;I-=k)
#define rep(i,x) for(register int i=h[x];i;i=last[x])
#define mn 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline void swap(int &a,int &b){
    int t=a;a=b;b=t;
}
int size,n,heap[mn];
inline void puth(int x){
    int now,next;
    heap[++size]=x;
    now=size;
    while(now>1){
        next=now>>1;
        if(heap[now]>=heap[next])
            return ;
        swap(heap[now],heap[next]);
        now=next;
    }
}
inline void geth(){
    cout<<heap[1]<<" ";
    return ;
}
inline int delh(){
    int now,next,res;
    res=heap[1];
    heap[1]=heap[size--];
    now=1;
    while(now*2<=size){
        next=now*2;
        if(next<size && heap[next+1]<heap[next])
            next++;
        if(heap[now]<=heap[next])
            return res;
        swap(heap[now],heap[next]);
        now=next;
    }
}
int main(){
    n=read();
    go(i,1,n,1){
        int x=read();
        puth(x);
    }
    go(i,1,n,1){
        geth();
        delh();
    }
    return 0;
}

4.冒泡排序

P1177 【模板】快速排序——20分代码
#include<iostream>
using namespace std;
inline void swapx(int &x,int &y){
    int t=x;x=y;y=t;
}
int n,a[100010];
int main() {
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n-i;j++)
            if(a[j]>a[j+1])
                swapx(a[j],a[j+1]);
    for(int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    return 0;
}

(三)DP算法

1.LCS(最长公共子序列)

P1439 【模板】最长公共子序列——AC代码
#include<bits/stdc++.h>
using namespace std;
#define go(i,j,n,k) for(register int i=j;i<=n;i+=k)
#define fo(i,j,n,k) for(register int i=j;i>=n;i-=k)
#define mn 100010
#define inf 2147483647
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-f;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int f[mn];
int a[mn],b[mn],c[mn];
int n,l;
int main(){
    n=read();
    go(i,1,n,1) a[i]=read(),c[a[i]]=i;
    go(i,1,n,1) b[i]=read(),f[i]=inf;
    f[0]=0,l=0;
    go(i,1,n,1){
        int le=0,ri=l,mid;
        if(c[b[i]]>f[l]){
            f[++l]=c[b[i]];
        }else{
            while(le<ri){
                mid=(le+ri)/2;
                if(f[mid]>c[b[i]]){
                    ri=mid;
                }else{
                    le=mid+1;
                }
            }
            f[le]=min(c[b[i]],f[le]);
        }
    }
    cout<<l;
    return 0;
} 

(四)树上算法

1.树链剖分

P3384 【模板】树链剖分——AC代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 200010
#define inf 1 << 30
#define ll long long
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > ‘9‘ || ch < ‘0‘){if (ch == ‘-‘)f = -f;ch = getchar();}
    while (ch >= ‘0‘ && ch <= ‘9‘){x = x * 10 + ch - ‘0‘;ch = getchar();}
    return x * f;
}
inline void write(int x){
    if (x < 0)putchar(‘-‘),x = -x;
    if (x > 9)write(x / 10);
    putchar(x % 10 + ‘0‘);
}
//This is AC head above...
int mod;
int n, m, r;
int b[mn];
struct segmenttree{
    int z[mn << 2], col[mn << 2];
    inline void update(int rt){
        z[rt] = (z[rt << 1] + z[rt << 1 | 1]) % mod;
    }
    inline int operation(int a,int b){
        return (a + b) % mod;
    }
    inline void color(int l,int r,int rt,int v){
        z[rt] += (r - l + 1) * v;
        col[rt] += v;
    }
    inline void push_col(int l,int r,int rt){
        if(col[rt]){
            int m = (l + r) >> 1;
            color(lson, col[rt]);
            color(rson, col[rt]);
            col[rt] = 0;
        }
    }
    inline void build(int l,int r,int rt){
        if(l==r){
            z[rt] = b[l] % mod;
            return;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        update(rt);
    }
    inline void modify(int l,int r,int rt,int nowl,int nowr,int v){
        if(nowl<=l && r<=nowr){
            color(bson, v);
            return;
        }
        int m = (l + r) >> 1;
        push_col(bson);
        if(nowl<=m)
            modify(lson, nowl, nowr, v);
        if(m<nowr)
            modify(rson, nowl, nowr, v);
        update(rt);
    }
    inline int query(int l,int r,int rt,int nowl,int nowr){
        if(nowl<=l && r<=nowr){
            return z[rt] % mod;
        }
        int m = (l + r) >> 1;
        push_col(bson);
        if(nowl<=m){
            if(m<nowr)
                return operation(query(lson, nowl, nowr), query(rson, nowl, nowr));
            else
                return query(lson, nowl, nowr);
        }else{
            return query(rson, nowl, nowr);
        }
    }
} tr;
//Line Segment Tree ----------------------------------------
struct edge{
    int v,nxt;
} e[mn<<1];
int h[mn],p;
int w[mn];
inline void add(int a,int b){
    p++;
    e[p].nxt=h[a];
    h[a]=p;
    e[p].v=b;
}
//adjacency list ------------------------------------------
int dep[mn], fa[mn], son[mn], id[mn], sze[mn], top[mn];
int cnt;
//arrs ----------------------------------------------------
void dfs1(int x,int f,int deep){
    dep[x] = deep;
    fa[x] = f;
    sze[x] = 1;
    int maxson = -1;
    rep(i,x){
        int v = e[i].v;
        if(v==f)
            continue;
        dfs1(v, x, deep + 1);
        sze[x] += sze[v];
        if(sze[v] > maxson)
            maxson = sze[v], son[x] = v;
    }
}
void dfs2(int x,int topf){
    id[x] = ++cnt;
    b[id[x]] = w[x];
    top[x] = topf;
    if(!son[x])
        return;
    dfs2(son[x], topf);
    rep(i,x){
        int v = e[i].v;
        if (v == son[x] || v == fa[x])
            continue;
        dfs2(v, v);
    }
}
//DFS -----------------------------------------------------
inline int query1(int x,int y){
    int ans = 0;
    while(top[x] != top[y]){
        if(dep[top[x]]<dep[top[y]])
            swap(x, y);
        ans += tr.query(root, id[top[x]], id[x]);
        ans %= mod;
        x = fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x, y);
    ans += tr.query(root, id[x], id[y]);
    ans %= mod;
    return ans;
}
inline void modify1(int x,int y,int v){
    v %= mod;
    while(top[x] != top[y]){
        if(dep[top[x]]<dep[top[y]])
            swap(x, y);
        tr.modify(root, id[top[x]], id[x], v);
        x = fa[top[x]];
    }
    if(dep[x]>dep[y])
        swap(x, y);
    tr.modify(root, id[x], id[y], v);
}
inline int query2(int x){
    return tr.query(root, id[x], id[x] + sze[x] - 1);
}
inline void modify2(int x,int v){
    v %= mod;
    tr.modify(root, id[x], id[x] + sze[x] - 1, v);
}
//Change and Query ----------------------------------------
int main(){
    n = read(), m = read(), r = read(), mod = read();
    go(i,1,n,1){
        w[i] = read();
    }
    go(i,1,n-1,1){
        int x = read(), y = read();
        add(x, y), add(y, x);
    }
    dfs1(r, 0, 1);
    dfs2(r, r);
    tr.build(root);
    go(i,1,m,1){
        int s = read();
        if(s==1){
            int x = read(), y = read(), z = read();
            modify1(x, y, z);
        }else if(s==2){
            int x = read(), y = read();
            cout << query1(x, y) << "\n";
        }else if(s==3){
            int x = read(), z = read();
            modify2(x, z);
        }else if(s==4){
            int x = read();
            cout << query2(x) << "\n";
        }
    }
    return 0;
}

我只是想问,,,

有几位大佬可以一个不差的看完了我3000+行的板子呢?

原文地址:https://www.cnblogs.com/yizimi/p/10056141.html

时间: 2024-10-10 11:54:51

【基本算置顶】各大算法&&数据结构模板的相关文章

织梦文档置顶并显示置顶文字或图标

织梦默认自带置顶功能,我们只需要在后台文档[文章排序]里对文档进行置顶操作就行了 模板标签中dede:arclist 和 dede:list 默认是按置顶排序优先排在前面,所以不需要特别的设置标签 显示[置顶]文字,这样调用 [field:sortrank runphp=yes]@me = time() < @me ? "[置顶]" : "";[/field:sortrank]复制 1 显示[置顶]图标,这样调用 [field:sortrank runphp=

在有序数据表中实现多记录上移下移置顶置底算法思路

引言 数据库应用中常需要在一个有序数据子集中,对指定的若干条记录进行上下移动.例如,管理员需要对新闻列表中的若干条新闻置顶,考试出卷时需要对选定题目进行上下移动重排顺序,等等. 总的应该场景在数据表中可以概括为如下模型: 数据表 TblData(id,fid,rank),id表示记录的唯一标识,fid指记录的父节点,rank代表父节点下兄弟的前后顺序,依次从1递增,没有空隙. 问题是要对相同fid下选中的若干个节点进行上下移动,如图1中的2个示例: 图 1 上移操作示例图 左侧示例是对第5.6两

数据挖掘十大算法之决策树详解(2)

在2006年12月召开的 IEEE 数据挖掘国际会议上(ICDM, International Conference on Data Mining),与会的各位专家选出了当时的十大数据挖掘算法( top 10 data mining algorithms ),可以参见文献[1].本博客已经介绍过的位列十大算法之中的算法包括: [1] k-means算法(http://blog.csdn.net/baimafujinji/article/details/50570824) [2] 支持向量机SVM

统治世界的十大算法

转自 http://geek.csdn.net/news/detail/32456 软件正在统治世界.而软件的核心则是算法.算法千千万万,又有哪些算法属于“皇冠上的珍珠”呢?Marcos Otero给出了他的看法. 什么是算法? 通俗而言,算法是一个定义明确的计算过程,可以一些值或一组值作为输入并产生一些值或一组值作为输出.因此算法就是将输入转为输出的一系列计算步骤. —Thomas H. Cormen,Chales E. Leiserson,算法入门第三版 简而言之,算法就是可完成特定任务的一

数据挖掘十大算法之决策树详解(1)

在2006年12月召开的 IEEE 数据挖掘国际会议上(ICDM, International Conference on Data Mining),与会的各位专家选出了当时的十大数据挖掘算法( top 10 data mining algorithms ),可以参见文献[1].本博客已经介绍过的位列十大算法之中的算法包括: [1] k-means算法(http://blog.csdn.net/baimafujinji/article/details/50570824) [2] 支持向量机SVM

[置顶] Android开发笔记(成长轨迹)

分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API 调用了未实现的OpenGL ES API函数,一般由于导入的第三方库如地图库,里面有用到OpenGL,但是模拟器的硬件默认是没有这个的,所以需要我们编辑模拟器Emulation Options选项勾选 Use Host GPU 然后重启模拟器再尝试,如果还是这个错误,那么我们只好用真机测试了. 2.

代码面试最常用的10大算法

摘要:面试也是一门学问,在面试之前做好充分的准备则是成功的必须条件,而程序员在代码面试时,常会遇到编写算法的相关问题,比如排序.二叉树遍历等等. 在程序员的职业生涯中,算法亦算是一门基础课程,尤其是在面试的时候,很多公司都会让程序员编写一些算法实例,例如快速排序.二叉树查找等等. 本文总结了程序员在代码面试中最常遇到的10大算法类型,想要真正了解这些算法的原理,还需程序员们花些功夫. 1.String/Array/Matrix 在Java中,String是一个包含char数组和其它字段.方法的类

Mysql数据库实现的简单置顶

Mysql数据库实现的简单置顶 1. 问题背景:小编要做一个文章管理的简单网页,用的是Mysql数据库.其中需要文章置顶功能,如图: 2. 最初的思路:机智的小编立刻大脑飞速运转,很快想到为存储文章的"article"表设定一个(int)型的"isTop"属性,0表示不置顶,大于0表示置顶且数字越大,优先级越高.显示的时候只需按照"isTop"降序显示.当用户需要将"id"为"001"的文章置顶时,后台只需

页面开启自启动置顶显示,页面持续获得焦点

首先讲一下本文的使用背景,现有以下需求: 将一个展示页面开机后自动全屏显示,要求运行期间不允许有任何弹窗弹出遮挡住页面,且页面应保持焦点以保证键盘可以操作页面. 开机自动启动我们可以将需要打开的页面的快捷方式或其他自启动的软件放在系统启动文件夹中,路径如下所示: C:\Users\WindowsUserNmae\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 其中"WindowsUserNmae"为使用电脑的用