CSP 前模板记录(黄题篇)

快要 \(CSP\) 了,还是啥都不会。

赶紧打几个板子复习一下,让自己认识到自己有多渣然后好好努力吧。

P1886 滑动窗口 /【模板】单调队列
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e6 + 10;
int n, k;
int a[N], q[N];

inline void fmin(){
    int head = 1, tail = 0;
    for(int i = 1; i <= n; i++){
        while(head <= tail && q[head] <= i - k) head++;
        while(head <= tail && a[i] <= a[q[tail]]) tail--;
        q[++tail] = i;
        if(i >= k)
            printf("%d ", a[q[head]]);
    }
    puts("");
}

inline void fmax(){
    int head = 1, tail = 0;
    for(int i = 1; i <= n; i++){
        while(head <= tail && q[head] <= i - k) head++;
        while(head <= tail && a[i] >= a[q[tail]]) tail--;
        q[++tail] = i;
        if(i >= k)
            printf("%d ", a[q[head]]);
    }
    puts("");    
}

int main(){
    n = read(), k = read();
    for(int i = 1; i <= n; i++)
        a[i] = read();
    fmin();
    fmax();
    return 0;
}
P5788 【模板】单调栈
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 3e6 + 10;
int n;
int a[N], stk[N], top;
int ans[N];

int main(){
    n = read();
    for(int i = 1; i <= n; i++)
        a[i] = read();
    for(int i = n; i >= 1; i--){
        while(top && a[stk[top]] <= a[i]) top--;
        ans[i] = stk[top];
        stk[++top] = i;
    }
    for(int i = 1; i <= n; i++)
        printf("%d ", ans[i]);
    puts("");
    return 0;
}
P3382 【模板】三分法
#include <iostream>
#include <cstdio>
#include <algorithm>
#define exp 1e-8

using namespace std;

int n;
double l, r;
double a[20];

inline double qpow(double a, int b){
    double res = 1;
    while(b){
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

inline double f(double x){
    double res = 0;
    for(int i = 1; i <= n + 1; i++)
        res += a[i] * qpow(x, n - i + 1); 
    return res;
}

int main(){
    scanf("%d%lf%lf", &n, &l, &r);
    for(int i = 1; i <= n + 1; i++)
        scanf("%lf", &a[i]);
    while(r - l > exp){
        double lmid = (l + r) / 2;
        double rmid = (lmid + r) / 2;
        if(f(lmid) > f(rmid)) r = rmid;
        else l = lmid;
    }
    printf("%.5f\n", l);
    return 0;
}
P3374 【模板】树状数组 1
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f; 
}

const int N = 5e5 + 10;
int n, m;
int c[N];

inline void update(int x, int y){
    for(; x <= n; x += x & (-x))
        c[x] += y;
}

inline int query(int x){
    int res = 0;
    for(; x; x -= x & (-x))
        res += c[x];
    return res;
}

int main(){
    n = read(), m = read();
    for(int i = 1; i <= n; ++i){
        int x = read();
        update(i, x);
    }
    while(m--){
        int op = read(), x = read(), y = read();
        if(op == 1) update(x, y);
        else printf("%d\n", query(y) - query(x - 1));
    }
    return 0;
}
P3368 【模板】树状数组 2
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 5e5 + 10;
int n, m;
int c[N];

inline void add(int x, int y){
    for(; x <= n; x += x & (-x))
        c[x] += y;
}

inline int query(int x){
    int res = 0;
    for(; x; x -= x & (-x))
        res += c[x];
    return res;
}

int main(){
    n = read(), m = read();
    int last = 0;
    for(int i = 1; i <= n; i++){
        int x = read();
        add(i, x - last), last = x;
    }
    while(m--){
        int op = read(), x = read();
        if(op == 1){
            int y = read(), k = read();
            add(x, k), add(y + 1, -k);
        }else printf("%d\n", query(x));
    }
    return 0;
}
P3811 【模板】乘法逆元
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long

using namespace std;

const ll N = 3e6 + 10;
ll n, mod;
ll inv[N];

signed main(){
    scanf("%lld%lld", &n, &mod);
    inv[1] = 1;
    puts("1");
    for(ll i = 2; i <= n; i++){
        inv[i] = mod - mod / i * inv[mod % i] % mod;
        printf("%lld\n", inv[i]);
    }
    return 0;
}
P3375 【模板】KMP字符串匹配
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 1e6 + 10;
char a[N], b[N];
int nxt[N];
int n, m;

int main(){
    scanf("%s%s", a + 1, b + 1);
    n = strlen(a + 1), m = strlen(b + 1);
    nxt[1] = 0;
    for(int i = 2, j = 0; i <= m; i++){
        while(j && b[i] != b[j + 1]) j = nxt[j];
        if(b[i] == b[j + 1]) j++;
        nxt[i] = j;
    }
    for(int i = 1, j = 0; i <= n; i++){
        while(j && a[i] != b[j + 1]) j = nxt[j];
        if(a[i] == b[j + 1]) j++;
        if(j == m){
            printf("%d\n", i - j + 1);
            j = nxt[j];
        }
    }
    for(int i = 1; i <= m; i++)
        printf("%d ", nxt[i]);
    puts("");
    return 0;
}
P3379 【模板】最近公共祖先(LCA)
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 5e5 + 10;
int n, m, s;
struct node{
    int v, nxt;
}edge[N << 1];
int head[N], tot;

inline void add(int x, int y){
    edge[++tot] = (node){y, head[x]};
    head[x] = tot;
}

int fa[N], son[N], siz[N], dep[N];

inline void dfs1(int x, int p){
    fa[x] = p, dep[x] = dep[p] + 1, siz[x] = 1;
    for(int i = head[x]; i; i = edge[i].nxt){
        int y = edge[i].v;
        if(y == p) continue;
        dfs1(y, x);
        siz[x] += siz[y];
        if(!son[x] || siz[y] > siz[son[x]])
            son[x] = y;
    }
}

int top[N], dfn[N], cnt;

inline void dfs2(int x, int topfa){
    top[x] = topfa, dfn[x] = ++cnt;
    if(!son[x]) return;
    dfs2(son[x], topfa);
    for(int i = head[x]; i; i = edge[i].nxt){
        int y = edge[i].v;
        if(y == fa[x] || y == son[x]) continue;
        dfs2(y, y);
    }
}

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(), s = read();
    for(int i = 1; i < n; i++){
        int u = read(), v = read();
        add(u, v), add(v, u);
    }
    dfs1(s, 0), dfs2(s, s);
    while(m--){
        int u = read(), v = read();
        printf("%d\n", lca(u, v));
    }
    return 0;
}
P1939 【模板】矩阵加速(数列)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long

using namespace std;

const ll mod = 1e9 + 7;
ll T, n;

struct matrix{
    ll num[5][5];
    matrix(){
        memset(num, 0, sizeof(num));
    }
    matrix operator * (const matrix &b) const{
        matrix r;
        for(ll i = 1; i <= 3; i++)
            for(ll j = 1; j <= 3; j++)
                for(ll k = 1; k <= 3; k++)
                    r.num[i][j] = (r.num[i][j] + num[i][k] * b.num[k][j]) % mod;
        return r;
    }
    matrix operator ^ (ll p) const{
        matrix r, a;
        memcpy(a.num, num, sizeof(num));
        r.num[1][1] = r.num[2][2] = r.num[3][3] = 1;
        for(; p; p >>= 1, a = a * a)
            if(p & 1) r = r * a;
        return r;
    }
}f, A;

signed main(){
    scanf("%lld", &T);
    while(T--){
        scanf("%lld", &n);
        A.num[1][1] = A.num[1][2] = A.num[3][1] = A.num[2][3] = 1;
        f.num[1][1] = f.num[1][2] = f.num[1][3] = 1;
        if(n <= 3){
            puts("1");
            continue;
        }
        // for(ll i = 1; i <= 10; i++){
        //     f = f * A;
        //     cout << f.num[1][1] << " " << " " << f.num[1][2] << " " << f.num[1][3] << endl;
        // }
        printf("%lld\n", (f * (A ^ (n - 3))).num[1][1]);
    }
    return 0;
}
P3385 【模板】负环
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;

const int N = 2e3 + 10;
const int M = 3e3 + 10;
int T, n, m;
struct node{
    int v, w, nxt;
}edge[M << 1];
int head[N], tot;

inline void add(int x, int y, int z){
    edge[++tot] = (node){y, z, head[x]};
    head[x] = tot;
}

int dis[N], vis[N], t[N];

inline bool spfa(){
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(t, 0, sizeof(t));
    dis[1] = 0, vis[1] = t[1] = 1;
    queue <int> q;
    q.push(1);
    while(!q.empty()){
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for(int i = head[x]; i; i = edge[i].nxt){
            int y = edge[i].v;
            if(dis[y] > dis[x] + edge[i].w){
                dis[y] = dis[x] + edge[i].w;
                if(!vis[y]){
                    if((++t[y]) >= n) return 1;
                    vis[y] = 1;
                    q.push(y);
                }
            }
        }
    }
    return 0;
}

int main(){
    scanf("%d", &T);
    while(T--){
        memset(head, 0, sizeof(head));
        tot = 0;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            if(w >= 0) add(u, v, w), add(v, u, w);
            else add(u, v, w);
        }
        puts(spfa() ? "YES" : "NO");
    }
    return 0;
}
P3865 【模板】ST 表
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5 + 10;
int n, m;
int f[N][20];

int main(){
    n = read(), m = read();;
    for(int i = 1; i <= n; i++){
        int a = read();
        f[i][0] = a;
    }
    for(int j = 1; j <= 20; j++)
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    while(m--){
        int l = read(), r = read();
        int k = log2(r - l + 1);
        printf("%d\n", max(f[l][k], f[r - (1 << k) + 1][k]));
    }
    return 0;
}
P4549 【模板】裴蜀定理
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int n, ans;

inline int gcd(int a, int b){
    if(!b) return a;
    return gcd(b, a % b);
}

int main(){
    scanf("%d%d", &n, &ans);
    if(ans < 0) ans = -ans;
    for(int i = 2, x; i <= n; i++){
        scanf("%d", &x);
        if(x < 0) x = -x;
        ans = gcd(ans, x);
    }
    printf("%d\n", ans);
}
P4779 【模板】单源最短路径(标准版)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5 + 10;
int n, m, s;
struct Que{
    int x, dis;
    bool operator < (const Que &b) const{
        return dis > b.dis;
    }
};
struct node{
    int v, w, nxt;
}edge[N << 2];
int head[N], tot;
int dis[N];

inline void add(int x, int y, int z){
    edge[++tot].v = y;
    edge[tot].w = z;
    edge[tot].nxt = head[x];
    head[x] = tot;
}

inline void dijkstra(int s){
    memset(dis, 0x3f, sizeof(dis));
    dis[s] = 0;
    priority_queue <Que> q;
    q.push((Que){s, 0});
    while(!q.empty()){
        Que now = q.top();
        q.pop();
        int x = now.x;
        if(dis[x] < now.dis) continue;
        for(int i = head[x]; i; i = edge[i].nxt){
            int y = edge[i].v;
            if(dis[y] > dis[x] + edge[i].w){
                dis[y] = dis[x] + edge[i].w;
                q.push((Que){y, dis[y]});
            }
        }
    }
}

int main(){
    n = read(), m = read(), s = read();
    for(int i = 1; i <= m; i++){
        int u = read(), v = read(), w = read();
        add(u, v, w);
    }
    dijkstra(s);
    for(int i = 1; i <= n; i++)
        printf("%d ", dis[i]);
    puts("");
    return 0;
}
posted @ 2021-10-21 20:30  xixike  阅读(96)  评论(0编辑  收藏  举报