OI模板复习

数学有关的东西

gcd:

可以交在传送门洛谷2152拿完20分就跑23333(正解需要高精+一堆处理)

#include <cstdio>
#include <cstring>
#include <algorithm>

long long a, b;

long long gcd(long long a, long long b) {
    if (b == 0) return (a);
    return (gcd(b, a % b));
}

int main () {
    scanf("%lld %lld", &a, &b);
    printf("%lld", gcd(a, b));
    return 0;
}

exgcd:

传送门洛谷1082

#include <cstdio>
#include <cstring>
#include <algorithm>

int a, b, x, y;

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

int main () {
    scanf("%d %d", &a, &b);
    exgcd(a, b, x, y);
    x = ((x % b) + b ) % b;
    printf("%d", x);
    return 0;
}

快速幂:

传送门洛谷1226

#include <cstdio>
#include <cstring>
#include <algorithm>

long long b, p, k;

long long qpow(long long base, long long v, long long mod) {
    long long ans = 1;
    while (v > 0) {
        if (v & 1) ans = (ans * base) % mod;
        base = (base * base) % mod;
        v = v >> 1;
    }
    return (ans);
}
int main () {
    scanf("%lld %lld %lld", &b, &p, &k);
    printf("%lld^%lld mod %lld=%lld", b, p, k, qpow(b, p, k));

    return 0;
}

欧拉筛法:

传送门洛谷3383

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 10000000 + 5000;
int n, m;
int prime[maxn], isp[maxn];
int ptot = 0;
int x;
int main () {
    scanf("%d %d", &n, &m);
    for (int i = 2; i <= n; i++) isp[i] = 1;
    for (int i = 2; i <= n; i++) {
        if (isp[i]) {
            ptot++;
            prime[ptot] = i;
        }
        long long k;
        for (int j = 1; j <= ptot && (k = 1ll * prime[j] * i) <= n; j++) {
            isp[k] = 0;
            if (!(i % prime[j])) break;
        }
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d", &x);
        if (isp[x]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
} 

最长不上升子序列:

传送门洛谷2757

#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 300000 + 500;
int n;
int a[maxn];
int d[maxn];
int len = 0;
int x;
int ans;

int main () {
    d[0] = 0x7fffffff;
    n = 1;
    while (scanf("%d", &a[n]) == 1) {
        if (a[n] <= d[len]) {
            len++;
            d[len] = a[n];
        } else {
            int l = 0, r = len; 
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (d[mid] >= a[n]) {
                    l = mid + 1;
                    ans = mid;
                }  else {
                    r = mid - 1;
                }
            }
            d[ans+1] = a[n];
        }
        n++;
    }
    printf("%d\n", len);
    memset(d, 0, sizeof(d));
    // printf("%d", n);
    n--;
    len = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] > d[len]) {
            len++;
            d[len] = a[i];
        } else {
            int l = 0, r = len;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (d[mid] < a[i]) {
                    l = mid + 1;
                    ans = mid;
                } else {
                    r = mid - 1;
                }
            }
            d[ans+1] = a[i];
        }
    }
    printf("%d", len);
    return 0;
}

高精度加法,读入,输出:

传送门洛谷1601
注意进位时要用+=

#include <cstdio>
#include <cstring>
#include <algorithm>

int tt[1000];
struct bigint {
    int num;
    int a[1000];
    void print() {
        for (int j = num; j >= 1; j--) {
            printf("%d", a[j]);
        }
        printf("\n");
    }
    void readint() {
        memset(tt, 0, sizeof(tt));
        char c = getchar();
        num = 0;
        while (c < '0' || c > '9') c = getchar();
        while (c >= '0' && c <= '9') {
            num++;
            tt[num] = c - '0';
            c = getchar();
        }
        for (int i = 1; i <= num; i++) 
            a[i] = tt[num - i + 1];
    }
    void clear0() {
        num = 0;
        memset(a, 0, sizeof(a));
    }
    void clear1() {
        num = 1;
        memset(a, 0, sizeof(a));
        a[1] = 1;
    }
};

bigint aa, bb;
bigint cc;
bigint operator + (bigint xx, bigint yy) {
    bigint cc;
    cc.clear0();
    cc.num = std :: max(xx.num, yy.num);
    for (int i = 1; i <= cc.num; i++) {
        cc.a[i] += xx.a[i] + yy.a[i];
        if (cc.a[i] >= 10) {
            cc.a[i+1] += cc.a[i] / 10;
            cc.a[i] = cc.a[i] % 10;
        }
    }
    if (cc.a[cc.num + 1] == 0) return (cc);
    cc.num++;
    while (cc.a[cc.num] >= 10) {
        cc.a[cc.num+1] += cc.a[cc.num] / 10;
        cc.a[cc.num] = cc.a[cc.num] % 10;
    }
    return (cc);
}

int main () {
    aa.readint();
    bb.readint();
    // aa.print();
    // bb.print();
    cc = aa + bb;
    cc.print();
    return 0;
}

矩阵快速幂:

传送门洛谷3390
手一抖就把乘号打成了加号

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 110;
const long long mod = 1e9 + 7;
int n;
struct data {
    long long a[maxn][maxn];
    void clear0(void) {
        memset(a, 0, sizeof(a));
    }
    void clear1(void) {
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= n; i++) a[i][i] = 1; 
    }
    void print() {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) printf("%d ", a[i][j]);
            printf("\n");
        }
    }
};
long long k;
data aa;
data ans;
data operator * (data xx, data yy) {
    data cc;
    cc.clear0();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) 
            for (int k = 1; k <= n; k++) cc.a[i][j] = (cc.a[i][j] + xx.a[i][k] * yy.a[k][j]) % mod;
    return (cc);
}

data qpow(data aa, long long v, long long mod) {
    data ans;
    ans.clear1();
    while (v > 0) {
        if (v & 1) ans = ans * aa;
        v = v >> 1;
        aa = aa * aa;
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) ans.a[i][j] %= mod;
    return ans;
}

int main () {
    scanf("%d %lld", &n, &k);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            scanf("%d", &aa.a[i][j]);
            aa.a[i][j] %= mod;
        }
    ans = qpow(aa, k, mod);
    ans.print();
    return 0;
}

数据结构:

树状数组:

传送门洛谷3374

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 550000;
int c[maxn];
int n, m;
int x;
int odd, y;
inline int lowbit(int x) {
    return (x & (-x));
}

void change(int x, int z) {
    while (x <= n) {
        c[x] += z;
        x += lowbit(x);
    }
}

long long xfind(int x) {
    long long ans = 0;
    while (x > 0) {
        ans += c[x];
        x -= lowbit(x);
    }
    return (ans);
}

int main () {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        change(i, x);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &odd, &x, &y);
        if (odd == 1) {
            change(x, y);
        } else {
            printf("%lld\n", xfind(y) - xfind(x-1));
        }
    }

    return 0;
}

线段树:

传送门洛谷3372
手抖数组没开三倍,,

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 110000;
struct data {
    int l, r;
    long long sum;
    long long lazy;
};
data p[maxn * 3];
int a[maxn];
int n, m;
int od, x, y, z;
void build(int x, int l, int r) {
    p[x].l = l;
    p[x].r = r;
    if (p[x].l == p[x].r) {
        p[x].sum = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(2 * x, l, mid);
    build(2 * x + 1, mid + 1, r);
    p[x].sum = p[2 * x].sum + p[2 * x + 1].sum;
}

void update(int x) {
    p[x].sum += p[x].lazy * (p[x].r - p[x].l + 1);
    if (p[x].l == p[x].r) {
        p[x].lazy = 0;
        return;
    }
    p[2 * x].lazy += p[x].lazy;
    p[2 * x + 1].lazy += p[x].lazy;
    p[x].lazy = 0;
}

void change(int x, int l, int r, int z) {
    if (p[x].l == l && p[x].r == r) {
        p[x].lazy += z;
        return;
    }
    if (p[x].lazy) update(x);
    int mid = (p[x].l + p[x].r) >> 1;
    if (r <= mid) change(2 * x, l, r, z);
    else if (l > mid) change(2 * x + 1, l, r, z);
    else {
        change(2 * x, l, mid, z);
        change(2 * x + 1, mid + 1, r, z);
    }
    p[x].sum = (p[2 * x].sum + p[2 * x + 1].sum + p[2 * x].lazy * (p[2 * x].r - p[2 * x].l + 1) + p[2 * x + 1].lazy * (p[2 * x + 1].r - p[2 * x + 1].l + 1));   
}

long long xfind(int x, int l, int r) {
    if (p[x].lazy) update(x);
    if (p[x].l == l && p[x].r == r) {
        return (p[x].sum);
    }
    int mid = (p[x].l + p[x].r) >> 1;
    if (r <= mid) return (xfind(2 * x, l, r));
    else if (l > mid) return (xfind(2 * x + 1, l, r));
    else return (xfind(2 * x, l, mid) + xfind(2 * x + 1, mid + 1, r));
}

int main () {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    build(1, 1, n);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &od, &x, &y);
        if (od == 1) {
            scanf("%d", &z);
            change(1, x, y, z);
        } else {
            printf("%lld\n", xfind(1, x, y));
        }
    }
    return 0;
}

单调队列:

传送门洛谷1886
改了一个世纪,,感觉单调队列有点虚,,错误点:

  • q1和q2数组存储的应该是下标而非数据,处理过程中弄混
  • 在前移队列尾指针时忘记控制尾指针小于头指针
#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1e6 + 500;
const int inf = 0x7fffffff;
int q1[maxn];       //  min
int q2[maxn];       //  max
int a[maxn];
int q1h = 1, q1t = 1;
int q2h = 1, q2t = 1;
int n, k;
int main () {
    freopen("window.in", "r", stdin);
    freopen("window.out", "w", stdout);
    scanf("%d %d", &n, &k);
    q2[0] = 0;
    q1[0] = 0;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    q1[1] = 1;
    for (int i = 2; i <= k; i++) {
        while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
        q1t++;
        q1[q1t] = i;
    }
    printf("%d ", a[q1[1]]);
    for (int i = k + 1; i <= n; i++) {
        while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
        q1t++;
        q1[q1t] = i;
        while (q1[q1h] <= i - k) q1h++;
        printf("%d ", a[q1[q1h]]);
    }
    q2[1] = 1;
    for (int i = 2; i <= k; i++) {
        while (a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
        q2t++;
        q2[q2t] = i;
    }
    printf("\n%d ", a[q2[1]]);
    for (int i = k + 1; i <= n; i++) {
        while(a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
        q2t++;
        q2[q2t] = i;
        while (q2[q2h] <= i - k) q2h++;
        printf("%d ", a[q2[q2h]]);
    }
    return 0;
}

第二次做就熟悉了好多
传送门洛谷1440

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 2000000 + 5000;
int q1[maxn];
int q1h = 1, q1t = 1;
int n, m;
int a[maxn];

int main () {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    printf("0\n");
    q1[1] = 1;
    printf("%d\n", a[1]);
    for (int i = 2; i <= m; i++) {
        while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
        q1t++;
        q1[q1t] = i;
        printf("%d\n", a[q1[1]]);
    }
    for (int i = m + 1; i < n; i++) {
        while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
        q1t++;
        q1[q1t] = i;
        while (q1[q1h] <= i - m) q1h++;
        printf("%d\n", a[q1[q1h]]);
    }
    return 0;
}

并查集:

传送门洛谷3367

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 10000 + 500;
int father[maxn];
int x, y, od;
int n, m;

int getfather(int x) {
    if (father[x] == x) return (x);
    return (father[x] = getfather(father[x]));
}

int main () {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) father[i] = i;
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &od, &x, &y);
        if (od == 1) {
            int tx = getfather(x);
            int ty = getfather(y);
            if (tx == ty) continue;
            father[tx] = ty;
        } else {
            int tx = getfather(x);
            int ty = getfather(y);
            if (tx == ty) printf("Y\n");
            else printf("N\n");
        }
    }

    return 0;
}

平衡树:

传送门洛谷3369

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 100000 + 5000;
int size[maxn], left[maxn], right[maxn], val[maxn];
int n, m;
int tot = 0;
int t = 0;
int oop, key;

void right_rotate(int &t) {
    int k = left[t];
    left[t] = right[k];
    right[k] = t;
    size[k] = size[t];
    size[t] = size[left[t]] + size[right[t]] + 1;
    t = k;
}
void left_rotate(int &t) {
    int k = right[t];
    right[t] = left[k];
    left[k] = t;
    size[k] = size[t];
    size[t] = size[left[t]] + size[right[t]] + 1;
    t = k;
}
void maintain(int &t, bool flag) {
    if (flag) {
        if (size[right[right[t]]] > size[left[t]]) {
            left_rotate(t);
        } else if (size[left[right[t]]] > size[left[t]]) {
            right_rotate(right[t]);
            left_rotate(t);
        } else return;
    } else {
        if (size[left[left[t]]] > size[right[t]]) {
            right_rotate(t);
        } else if (size[right[left[t]]] > size[right[t]]) {
            left_rotate(left[t]);
            right_rotate(t);
        }  else return;
    }
    maintain(left[t], 0);
    maintain(right[t], 1);
    maintain(t, 0);
    maintain(t, 1);
}
void insert1(int &t, int v) {
    if (t == 0) {
        tot++;
        t = tot;
        size[t] = 1;
        val[t] = v;
        left[t] = 0;
        right[t] = 0;
    } else {
        size[t]++;
        if (v < val[t]) {
            insert1(left[t], v); 
        } else {
            insert1(right[t], v);
        }
        maintain(t, v >= val[t]);
    }
}

int delete2(int &t, int v) {
    int cur = 0;
    size[t]--;
    if (v == val[t] || (v > val[t] && right[t] == 0) || (v < val[t] && left[t] == 0)) {
        cur = val[t];
        if (left[t] == 0 || right[t] == 0) {
            t = left[t] + right[t];
        } else {
            val[t] = delete2(left[t], v + 1);
        }
    } else if (v < val[t]) cur = delete2(left[t], v);
    else cur = delete2(right[t], v);
    return (cur);
}

int rank3(int &t, int v) {
    if (t == 0) return (1);
    if (val[t] >= v) {
        return (rank3(left[t], v));
    } else if (val[t] < v) {
        return (rank3(right[t], v) + size[left[t]] + 1);
    }
}

int find4(int &t, int v) {
    if (size[left[t]] + 1 == v) return (val[t]);
    else if (size[left[t]] + 1 < v) return (find4(right[t],v - size[left[t]] - 1));
    else return (find4(left[t], v));
}

int pre5(int &t, int v) {
    if (t == 0) return (-1);
    if (v <= val[t]) {
        return (pre5(left[t], v));
    } else {
        int cur = pre5(right[t], v);
        if (cur == -1) return (val[t]);
        return (cur);
    }
}

int succ6(int &t, int v) {
    if (t == 0) return (-1);
    if (v >= val[t]) {
        return (succ6(right[t], v)); 
    } else {
        int cur = succ6(left[t], v);
        if (cur == -1) return (val[t]);
        return (cur);
    }
}


int main () {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &oop, &key);
        if (oop == 1) insert1(t, key);
        if (oop == 2) delete2(t, key);
        if (oop == 3) printf("%d\n", rank3(t,key));
        if (oop == 4) printf("%d\n", find4(t, key));
        if (oop == 5) printf("%d\n", pre5(t, key));
        if (oop == 6) printf("%d\n", succ6(t, key));
    }

    return 0;
}

算法

最小生成树

传送门洛谷3366

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 6000;
const int maxm = 210000;
struct data {
    int from;
    int to;
    int val;
};
int father[maxn];
data p[maxm];
int n, m;
int x, y, z;
long long ans = 0;
int cur;
bool cmp(data aa, data bb) {
    return (aa.val < bb.val);
}

int getfather(int x) {
    if (father[x] == x) return (x);
    return (father[x] = getfather(father[x]));
}

int main () {
    scanf("%d %d", &n, &m);
    cur = n;
    for (int i = 1; i <= n; i++) father[i] = i;
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &p[i].from, &p[i].to, &p[i].val);
    }
    std :: sort(p + 1, p + m + 1, cmp);
    for (int i = 1; i <= m; i++) {
        int tx = getfather(p[i].from);
        int ty = getfather(p[i].to);
        if (tx != ty) {
            cur--;
            father[tx] = ty;
            ans += p[i].val;
        }
    }
    if (cur > 1) printf("orz");
    else printf("%lld", ans);
    return 0;
}

匈牙利算法:

传送门洛谷3386

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 2200;
int line[maxn][maxn];
int flag[maxn];
int vis[maxn];
int n, m, e;
int ans = 0;
int x, y;

bool xfind(int x) {
    for (int j = 1; j <= m; j++) {
        if (line[x][j] && flag[j] == 0) {
            flag[j] = 1;
            if (vis[j] == 0 || xfind(vis[j])) {
                vis[j] = x;
                return 1;
            }
        }
    }
    return 0;
}

int main () {
    scanf("%d %d %d", &n, &m, &e);
    for (int i = 1; i <= e; i++) {
        scanf("%d %d", &x, &y);
        line[x][y] = 1;
    }
    for (int i = 1; i <= n; i++) {
        memset(flag, 0, sizeof(flag));
        if (xfind(i)) ans++;
    }
    printf("%d", ans);
    return 0;
}

SPFA:

传送门

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 15000;
const int maxm = 500000 + 5000;
const int inf = 0x7fffffff;
int dis[maxn], que[maxn], vis[maxn];
int last[maxn], pre[maxm], other[maxm], val[maxm];
int tot = 1;
int n, m, s;
int x, y, z;

void add(int x, int y, int z) {
    tot++;
    pre[tot] = last[x];
    last[x] = tot;
    other[tot] = y;
    val[tot] = z;
}
void spfa(int s) {
    que[1] = s;
    for (int i = 1; i <= n; i++) dis[i] = inf;
    dis[s] = 0;
    int h = 0, t = 1;
    while (h != t) {
        h = (h + 1) % maxn;
        int cur = que[h];
        vis[cur] = 0;
        for (int p = last[cur]; p; p = pre[p]) {
            int q = other[p];
            if (dis[q] > dis[cur] + val[p]) {
                dis[q] = dis[cur] + val[p];
                if (vis[q] == 0) {
                    vis[q] = 1;
                    t = (t + 1) % maxn;
                    que[t] = q;
                }
            }
        }
    }
}
int main () {
    scanf("%d %d %d", &n, &m, &s);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y, z);
    }
    spfa(s);
    for (int i = 1; i <= n; i++) printf("%d ", dis[i]);

    return 0;
}

堆+dijkstra:

传送门洛谷3371

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxn = 12000;
const int maxm = 550000;
const int inf = 0x7fffffff;
int n, m;
int s;
int last[maxn], pre[maxm], other[maxm], len[maxm];
int dis[maxn];
bool vis[maxn];
int tot = 0;
int x, y, z;
struct point{
    int dis;
    int num;
    point(int num, int dis) : dis(dis), num(num) {}
};
bool operator < (point aa, point bb) {
    return (aa.dis > bb.dis);
}

std :: priority_queue <point> q1;

void add(int x, int y, int z) {
    tot++;
    pre[tot] = last[x];
    last[x] = tot;
    other[tot] = y;
    len[tot] = z;
}

void dijkstra(int s) {
    for (int i = 1; i <= n; i++) {
        dis[i] = inf;
        q1.push(point(i, dis[i]));
    }
    dis[s] = 0;
    q1.push(point(s, dis[s]));
    while (!q1.empty()) {
        point kkk = q1.top();
        q1.pop();
        if (kkk.dis == inf) return;
        if (vis[kkk.num]) continue;
        vis[kkk.num] = 1;
        for (int p = last[kkk.num]; p; p = pre[p]) {
            int q = other[p];
            if (dis[q] > dis[kkk.num] + len[p]) {
                dis[q] = dis[kkk.num] + len[p];
                q1.push(point(q, dis[q]));
            }
        }
    }

}

int main () {
    scanf("%d %d %d", &n, &m, &s);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y, z);
    }
    dijkstra(s);
    for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
    return 0;
}

KMP:

传送门洛谷3375

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1100000;
const int maxm = 1100;
int next[maxm];
char s1[maxn];
char s2[maxm];



int main () {
    scanf("%s %s", s1, s2);
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    for (int i = 1,  p = 0; i < len2; i++) {
        while (s2[i] != s2[p] && p > 0) p = next[p-1];
        if (s2[i] == s2[p]) p++;
        next[i] = p;
    }
    for (int i = 0, p = 0; i < len1; i++) {
        while (s1[i] != s2[p] && p > 0) p = next[p-1];
        if (s1[i] == s2[p]) p++;
        if (p == len2) {
            printf("%d\n", i - len2 + 2);
            p = next[p-1];
        }
    }
    for (int i = 0; i < len2; i++) printf("%d ", next[i]);
    return 0;
}

倍增LCA:

传送门洛谷3379

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 550000;
int n, m, s;
int last[maxn], pre[maxn * 2], other[maxn * 2];
int jump[maxn][30];
int dis[maxn];
int tot = 0;
int x, y;

void add(int x, int y) {
    tot++;
    pre[tot] = last[x];
    last[x] = tot;
    other[tot] = y;
}
void dfs(int x, int come) {
    jump[x][0] = come;
    dis[x] = dis[come] + 1;
    for (int p = last[x]; p; p = pre[p]) {
        int q = other[p];
        if (q == come) continue;
        dfs(q, x);
    }
}

int lca(int x, int y) {
    if (dis[x] < dis[y]) std :: swap(x, y);
    if (dis[x] != dis[y]) { 
        for (int j = 25; j >= 0; j--) 
            if (dis[jump[x][j]] > dis[y]) x = jump[x][j];
        x = jump[x][0];
    }
    if (x == y) return (x);
    for (int j = 25; j >= 0; j--) {
        if (jump[x][j] != jump[y][j]) {
            x = jump[x][j];
            y = jump[y][j];
        }
    }
    return jump[x][0];
}

int main () {
    scanf("%d %d %d", &n, &m, &s);
    for (int i = 1; i < n; i++) {
        scanf("%d %d", &x, &y);
        add(x, y);
        add(y, x);
    }
    dfs(s, 0);
    for (int i = 1; i <= 25; i++) 
        for (int j = 1; j <= n; j++) 
            jump[j][i] = jump[jump[j][i-1]][i-1];
    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &x, &y);
        printf("%d\n", lca(x, y));
    }
    return 0;
}

Tarjan求环:

传送门洛谷2661

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 300000;
int next[maxn];
int dfn[maxn], low[maxn], size[maxn], belong[maxn];
bool vis[maxn];
int sta[maxn];
int statot = 0;
int cur = 0;
int tim = 0;
int n;
int ans = 0x7fffffff;


void tarjan(int x) {
    tim++;
    dfn[x] = low[x] = tim;
    statot++;
    vis[x] = 1;
    sta[statot] = x;
    int q = next[x];
    if (!dfn[q]) {
        tarjan(q);
        low[x] = std :: min(low[x], low[q]);
    } else if (vis[q]) {
        low[x] = std :: min(dfn[q], low[x]);
    }
    if (dfn[x] == low[x]) {
        cur++;
        while (sta[statot] != x) {
            belong[sta[statot]] = cur;
            vis[sta[statot]] = 0;
            size[cur]++;
            statot--;
        }
        belong[x] = cur;
        statot--;
        size[cur]++;
    }
}

int main () {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &next[i]);
    for (int i = 1; i <= n; i++) {
        if (!dfn[i]) tarjan(i);
    }
    for (int i = 1; i <= cur; i++) {
        if (size[i] > 1) ans = std :: min(ans, size[i]);
    }
    printf("%d", ans);
    return 0;
}

归并排序:

传送门洛谷1177

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 100000 + 5000;
int tmp[maxn];
int a[maxn];
int n;


void merg(int *a, int l, int mid, int r) {
    int cur = 1;
    int k1 = l;
    int k2 = mid + 1;
    while (k1 <= mid && k2 <= r) {
        if (a[k1] < a[k2]) {
            tmp[cur] = a[k1];
            cur++;
            k1++;
        } else {
            tmp[cur] = a[k2];
            cur++;
            k2++;
        }
    }
    while (k1 <= mid) {
        tmp[cur] = a[k1];
        cur++;
        k1++;
    }
    while (k2 <= mid) {
        tmp[cur] = a[k2];
        k2++;
        cur++;
    }
    memcpy(a + l, tmp + 1, sizeof(int) * (cur - 1));
}
void m_sort(int *a, int l, int r) {
    if (l < r) {
        int mid = (l + r) >> 1;
        m_sort(a, l, mid);
        m_sort(a, mid + 1, r);
        merg(a, l, mid, r);
    }
}
int main () {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    m_sort(a, 1, n);
    for (int i = 1; i <= n; i++) printf("%d ", a[i]);
    return 0;
}

网络流(dinic):

传送门洛谷3376

#include <cstdio>
#include <algorithm>
#include <cstring>
using std :: min;
const int maxm = 200000 + 1000;
const int maxn = 10000 + 500;
int last[maxn], pre[maxm], other[maxm], cap[maxm];
int tot = 1;
int s, t, n, m;
int x, y, z;
int dis[maxn], vis[maxn];
int que[maxn];


void add(int x, int y, int z) {
    tot++;
    pre[tot] = last[x];
    last[x] = tot;
    other[tot] = y;
    cap[tot] = z;
}
bool bfs(void) {
    memset(dis, 0, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    int queh = 0, quet = 1;
    que[1] = s;
    vis[s] = dis[s] = 1;
    while (queh < quet) {
        queh++;
        int cur = que[queh];
        for (int p = last[cur]; p; p = pre[p]) {
            int q = other[p];
            if (cap[p] && !vis[q]) {
                vis[q] = 1;
                dis[q] = dis[cur] + 1;
                quet++;
                que[quet] = q; 
            }
        } 
    }
    return (dis[t] > 0);
}
int dinic(int x, int flow) {
    if (x == t) return (flow);
    int ret = 0;
    for (int p = last[x]; p; p = pre[p]) {
        int q = other[p];
        if (cap[p] && flow && dis[q] == dis[x] + 1) {
            int push = dinic(q, min(cap[p], flow));
            if (!push) dis[q] = 0;
            flow -= push;
            ret += push;
            cap[p] -= push;
            cap[p ^ 1] += push;
        }
    }
    return (ret);
}
int main () {
    scanf("%d %d %d %d", &n, &m, &s, &t);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y, z);
        add(y, x, 0);
    }
    int ans = 0;
    while (bfs()) {
        ans += dinic(s, 0x7fffffff);
    } 
    printf("%d\n", ans);
    return 0;
}

字符串hash:

传送门洛谷3370

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int mod = 1e7 + 19;
const int base = 31;
const int step = 72;
int hasht[mod];
char s[1600];
int n;
int ans = 0;
char hs[10005][1600];
int tot = 0;
int main () {
    ios_base :: sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s;
        long long cur = 0;
        int len = strlen(s);
        for (int i = 0; i < len; i++) {
            cur = (cur * base + (int)s[i]) % mod;
        }
        bool ft = 0;
        while (hasht[cur] != 0) {
            if (strcmp(hs[hasht[cur]], s) == 0) {
                ft = 1;
                break;
            }
            cur = (cur + step) % mod;
        }
        if (ft) continue;
        tot++;
        hasht[cur] = tot;
        ans++;
        strcpy(hs[tot], s);
    }    
    cout << ans << endl;
    return 0;
}
发布了90 篇原创文章 · 获赞 65 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ctsnevermore/article/details/53158548
OI
今日推荐