NOIP前板子复习

再不复习板子我就是 [ 数据删除 ]

高精度

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

const int power = 4, base = 10000; //修改压位 
char a[233333], b[233333];
//初始化 
struct HP
{
    int len, p[2333];
    HP() { len = 0; memset(p, 0, sizeof(p)); }
    HP(char *s)
    {
        len = (strlen(s) + power - 1) / power;
        memset(p, 0, sizeof(p));
        for(int i = 0, t = 0, w; i < strlen(s); i++, w *= 10)
        {
            if(i % power == 0) t++, w = 1;
            p[t] += (s[i] - '0') * w;
        }
    }
    void rev() { reverse(p + 1, p + len + 1); }
    void add(int k) { if(len || k) p[++len] = k; }
    void print()
    {
        printf("%d", p[len]);
        for(int i = len - 1; i > 0; i--) printf("%0*d", power, p[i]);
        printf("
");
    }
} p, q, ans;
//重载运算符 
bool operator < (const HP &a, const HP &b)
{
    if(a.len < b.len) return true;
    if(a.len > b.len) return false;
    for(int i = a.len; i > 0; i--)
        if(a.p[i] != b.p[i]) return a.p[i] < b.p[i];
    return false;
}
HP operator + (const HP &a, const HP &b)
{
    HP c = a;
    c.len = max(a.len, b.len);
    for(int i = 1; i <= c.len; i++)
    {
        c.p[i] += b.p[i];
        c.p[i + 1] += c.p[i] / base;
        c.p[i] %= base;
    }
    if(c.p[c.len + 1]) c.len++;
    return c;
}
HP operator - (const HP &a, const HP &b)
{
    HP c = a;
    for(int i = 1; i <= c.len; i++)
    {
        c.p[i] -= b.p[i];
        if(c.p[i] < 0) c.p[i] += base, c.p[i + 1]--;
    }
    while(c.len && !c.p[c.len]) c.len--;
    return c;
}
HP operator * (const HP &a, const HP &b)
{
    HP c;
    c.len = a.len + b.len - 1;
    for(int i = 1; i <= a.len; i++)
        for(int j = 1; j <= b.len; j++)
        {
            c.p[i + j - 1] += a.p[i] * b.p[j];
            c.p[i + j] += c.p[i + j - 1] / base;
            c.p[i + j - 1] %= base;
        }
    while(c.p[c.len + 1]) c.len++;
    return c;
}
HP operator / (const HP &a, const HP &b)
{
    HP u, v;
    u.len = a.len;
    for(int i = a.len; i > 0; i--)
    {
        v.add(a.p[i]), v.rev();
        while(!(v < b)) v = v - b, u.p[i]++;
        v.rev();
    }
    while(u.len && !u.p[u.len]) u.len--;
    return u;
}
HP operator % (const HP &a, const HP &b) { return a - (a / b) * b; }
//以下是洛谷P1932主函数
int main()
{
    scanf("%s", &a), scanf("%s", &b);
    reverse(a, a + strlen(a)), reverse(b, b + strlen(b));
    p = HP(a), q = HP(b);
    ans = p + q; ans.print();
    if(p < q) { printf("-"); ans = q - p; }
    else ans = p - q;
    ans.print();
    ans = p * q; ans.print(); 
    ans = p / q; ans.print();
    ans = p % q; ans.print();
    return 0;
}

二分查找

//估计没有人写这么骚气的二分查找吧...
int l = left_limit, r = right_limit;
while(l + 1 < r)
{
    int mid = (l + r) >> 1;
    if(check(mid)) l = mid; //or r = mid;
    else r = mid; //or l = mid;
} 
st 1:
if(check(l)) ans = l;
else ans = r;
st 2:
if(check(r)) ans = r;
else ans = l;

tarjan 缩点

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

const int N = 10006, M = 100006;
struct edge
{
    int nxt, to;
} e[M];
int n, m, ans = 0, cnt = 0, id = 0, top = 0, col = 0;
int a[N], head[N], low[N], dfn[N], c[N], st[N], s[M], t[M];
int val[N], f[N], du[N], vis[N];

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

void add(int x, int y)
{
    e[++cnt] = (edge) { head[x], y };
    head[x] = cnt;
}

void dfs(int x) //板子部分
{
    dfn[x] = low[x] = ++id;
    st[++top] = x;
    vis[x] = 1;
    for(int i = head[x]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        if(!dfn[v]) { dfs(v); low[x] = min(low[x], low[v]); }
        else if(vis[v]) low[x] = min(low[x], dfn[v]);
    }
    if(dfn[x] == low[x])
    {
        col++;
        st[top + 1] = -1;
        while(st[top + 1] != x)
        {
            c[st[top]] = col;
            vis[st[top--]] = 0;
        }
    }
}

void top_sort()
{
    int m = col;
    for(int i = 1; i <= col; i++) f[i] = val[i];
    queue <int> q;
    for(int i = 1; i <= col; i++) if(!du[i]) q.push(i);
    while(!q.empty())
    {
        int a = q.front();
        q.pop();
        for(int i = head[a]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            du[v]--;
            f[v] = max(f[v], f[a] + val[v]);
            if(!du[v]) q.push(v);
        }
    }
    for(int i = 1; i <= col; i++) ans = max(ans, f[i]);
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i <= m; i++)
    {
        s[i] = read(), t[i] = read();
        add(s[i], t[i]);
    }
    memset(dfn, 0, sizeof(dfn));
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= n; i++) if(!dfn[i]) dfs(i);
    memset(head, 0, sizeof(head));
    memset(val, 0, sizeof(val));
    cnt = 0;
    for(int i = 1; i <= m; i++)
        if(c[s[i]] != c[t[i]])
        {
            add(c[s[i]], c[t[i]]);
            du[c[t[i]]]++;
        }
    for(int i = 1; i <= n; i++) val[c[i]] += a[i];
    top_sort();
    printf("%d", ans);
    return 0;
}

二分图最大匹配

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

const int N = 1010;
int n, m, E, ans = 0, e[N][N], girl[N], use[N];

bool find(int x)
{
    for(int j = 1; j <= m; j++)
        if(e[x][j] == 1 && use[j] == 0)
        {
            use[j] = 1;
            if(girl[j] == 0 || find(girl[j]))
            {
                girl[j] = x;
                return true;
            }
        }
    return false;
}

int main()
{
    scanf("%d%d%d", &n, &m, &E);
    memset(e, 0, sizeof(e));
    memset(girl, 0, sizeof(girl));
    for(int u, v, i = 1; i <= E; i++)
    {
        scanf("%d%d", &u, &v);
        if(u < 1 || u > n || v < 1 || v > m) continue;
        e[u][v] = 1;
    }
    for(int i = 1; i <= n; i++)
    {
        memset(use, 0, sizeof(use));
        ans += find(i);
    }
    printf("%d", ans);
    return 0;
}

状压 dp 枚举子集

for(int i = S; i; i = ((i - 1) & S))

Kruskal 最小生成树

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

const int N = 2333333;
LL n, m, ans = 0, f[N];
struct edge { LL u, v, w; } e[N];
bool cmp(edge a, edge b) { return a.w < b.w; }
LL find(LL x) { return x == f[x] ? x : f[x] = find(f[x]); }

int main()
{
    scanf("%lld%lld", &n, &m);
    for(int i = 1; i <= n; i++) f[i] = i;
    for(int i = 1; i <= m; i++)
        scanf("%lld%lld%lld", &e[i].u, &e[i].v, &e[i].w);
    sort(e + 1, e + m + 1, cmp);
    for(int i = 1; i <= m; i++)
        if(find(e[i].u) != find(e[i].v))
        {
            f[find(e[i].u)] = find(e[i].v);
            ans += e[i].w;
        }
    printf("%lld", ans);
    return 0;
} 

倍增求 LCA

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

const int N = 500010;
struct edge { int nxt, to; } e[N << 1];
int n, m, s, cnt = 0, u, v, f[N][23], deep[N], head[N];

void dfs(int x, int fa)
{
    deep[x] = deep[fa] + 1;
    f[x][0] = x, f[x][1] = fa;
    for(int i = 2; i <= 20; i++)
        f[x][i] = f[f[x][i - 1]][i - 1];
    for(int i = head[x]; i; i = e[i].nxt)
        if(e[i].to != fa) dfs(e[i].to, x);
}
int LCA(int x, int y)
{
    if(deep[x] < deep[y]) swap(x, y);
    for(int i = 20; i >= 0; i--)
        if(deep[f[x][i]] >= deep[y]) x = f[x][i];
    if(x == y) return x;
    for(int i = 20; i >= 0; i--)
        if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    return f[x][1];
}
void add(int x, int y) { e[++cnt] = (edge) { head[x], y }; head[x] = cnt; }

int main()
{
    scanf("%d%d%d", &n, &m, &s);
    memset(head, 0, sizeof(head));
    for(int i = 1; i < n; i++)
        scanf("%d%d", &u, &v), add(u, v), add(v, u);
    deep[0] = 0, dfs(s, 0);
    while(m--) scanf("%d%d", &u, &v), printf("%d
", LCA(u, v));
    return 0;
}

spfa

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;

const int N = 2333333;
struct edge { LL nxt, to, w; } e[N << 1];
LL n, m, s, cnt = 0, head[N], dis[N], vis[N];

void add(LL x, LL y, LL w)
{
    e[++cnt] = (edge) { head[x], y, w };
    head[x] = cnt;
}

void spfa()
{
    for(int i = 0; i <= n + 1; i++) dis[i] = (1 << 31) - 1;
    memset(vis, 0, sizeof(vis));
    queue <LL> q;
    q.push(s);
    vis[s] = 1, dis[s] = 0;
    while(!q.empty())
    {
        LL a = q.front();
        q.pop();
        vis[a] = 0;
        for(int i = head[a]; i; i = e[i].nxt)
        {
            LL v = e[i].to;
            if(dis[v] > dis[a] + e[i].w)
            {
                dis[v] = dis[a] + e[i].w;
                if(!vis[v]) { vis[v] = 1; q.push(v); }
            }
        }
    }
}

int main()
{
    scanf("%lld%lld%lld", &n, &m, &s);
    for(LL u, v, w, i = 1; i <= m; i++)
    {
        scanf("%lld%lld%lld", &u, &v, &w);
        add(u, v, w);
    }
    spfa();
    for(int i = 1; i <= n; i++) printf("%lld ", dis[i]);
    return 0;
}

dijkstra + 堆优化

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;

const int N = 2333333;
struct edge { LL nxt, to, w; } e[N];
LL n, m, s, cnt = 0, vis[N], dis[N], head[N];

void add(LL x, LL y, LL w)
{
    e[++cnt] = (edge) { head[x], y, w };
    head[x] = cnt;
}

struct node
{
    LL x, dis;
    friend bool operator < (node x, node y) { return x.dis > y.dis; }
};

void dijkstra()
{
    priority_queue <node> q;
    memset(dis, 0x7f7f7f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[s] = 0, q.push((node) { s, 0 });
    while(!q.empty())
    {
        LL a = q.top().x;
        q.pop();
        if(vis[a]) continue;
        vis[a] = 1;
        for(int i = head[a]; i; i = e[i].nxt)
        {
            LL v = e[i].to;
            if(dis[v] > dis[a] + e[i].w)
            {
                dis[v] = dis[a] + e[i].w;
                if(!vis[v]) q.push((node) { v, dis[v] });
            }
        }
    }
}

int main()
{
    scanf("%lld%lld%lld", &n, &m, &s);
    memset(head, 0, sizeof(head));
    for(LL u, v, w, i = 1; i <= m; i++)
        scanf("%lld%lld%lld", &u, &v, &w), add(u, v, w);
    dijkstra();
    for(int i = 1; i <= n; i++) printf("%lld ", dis[i]);
    return 0;
}

并查集

用时 (mathrm{2 space min})

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

const int N = 2333333;
int n, m, f[N];
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) f[i] = i;
    for(int x, y, z, i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &z, &x, &y);
        if(z == 1) f[find(x)] = find(y);
        else
        {
            if(find(x) == find(y)) printf("Y
");
            else printf("N
");
        }
    }
    return 0;
}

树状数组

用时 (5 space mathrm{min})

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define lowbit(x) (x & (-x))
using namespace std;

const int N = 2333333;
LL n, m, t[N];

void add(LL x, LL k) { while(x <= n) t[x] += k, x += lowbit(x); }
LL query(LL x)
{
    LL res = 0;
    while(x) res += t[x], x -= lowbit(x);
    return res;
}

int main()
{
    scanf("%lld%lld", &n, &m);
    for(LL a, i = 1; i <= n; i++) scanf("%d", &a), add(i, a);
    for(LL opt, x, y, i = 1; i <= m; i++)
    {
        scanf("%lld%lld%lld", &opt, &x, &y);
        if(opt == 1) add(x, y);
        else printf("%lld
", query(y) - query(x - 1));
    }
    return 0;
}

线段树 单点修改 + 区间查询

用时 (7 space mathrm{min})

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;

const LL N = 666666;
LL n, m, a[N], sum[N << 2];

struct Segment_Tree
{
    void push_up(LL x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
    void build(LL x, LL l, LL r)
    {
        if(l == r)
        {
            sum[x] = a[l];
            return ;
        }
        LL mid = (l + r) >> 1;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        push_up(x);
    }
    void update(LL x, LL l, LL r, LL std, LL k)
    {
        if(r < std || l > std) return ;
        if(l == std && r == std)
        {
            sum[x] += k;
            return ;
        }
        LL mid = (l + r) >> 1;
        update(x << 1, l, mid, std, k);
        update(x << 1 | 1, mid + 1, r, std, k);
        push_up(x);
    }
    LL query(LL x, LL l, LL r, LL stdl, LL stdr)
    {
        if(l > stdr || r < stdl) return 0;
        if(stdl <= l && stdr >= r) return sum[x];
        LL mid = (l + r) >> 1;
        return query(x << 1, l, mid, stdl, stdr) + 
        query(x << 1 | 1, mid + 1, r, stdl, stdr);
        push_up(x);
    }
} tree;

int main()
{
    scanf("%lld%lld", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    tree.build(1, 1, n);
    for(LL opt, x, y, i = 1; i <= m; i++)
    {
        scanf("%lld%lld%lld", &opt, &x, &y);
        if(opt == 1) tree.update(1, 1, n, x, y);
        else printf("%lld
", tree.query(1, 1, n, x, y));
    }
    return 0;
}

线段树 区间修改 + 单点查询

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

const int N = 2333333;
int n, m, a[N], tag[N], sum[N];

struct Segment_Tree
{
    void push_up(int x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
    void push_down(int x, int l, int r)
    {
        int mid = (l + r) >> 1;
        tag[x << 1] += tag[x];
        tag[x << 1 | 1] += tag[x];
        sum[x << 1] += tag[x] * (mid - l + 1);
        sum[x << 1 | 1] += tag[x] * (r - mid);
        tag[x] = 0;
    }
    void build(int x, int l, int r)
    {
        if(l == r)
        {
            sum[x] = a[l];
            return ;
        } 
        int mid = (l + r) >> 1;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        push_up(x);
    }
    void update(int x, int l, int r, int stdl, int stdr, int k)
    {
        if(l > stdr || r < stdl) return ;
        if(stdl <= l && stdr >= r)
        {
            tag[x] += k, sum[x] += k * (r - l + 1);
            push_down(x, l, r);
            return ;
        }
        int mid = (l + r) >> 1;
        push_down(x, l, r);
        update(x << 1, l, mid, stdl, stdr, k);
        update(x << 1 | 1, mid + 1, r, stdl, stdr, k);
        push_up(x);
    }
    int query(int x, int l, int r, int std)
    {
        if(l > std || r < std) return 0;
        if(l == std && r == std) return sum[x];
        int mid = (l + r) >> 1;
        push_down(x, l, r);
        return query(x << 1, l, mid, std) + 
        query(x << 1 | 1, mid + 1, r, std);
        push_up(x);
    }
} tree;

int main()
{
    scanf("%d%d", &n, &m);
    memset(tag, 0, sizeof(tag));
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    tree.build(1, 1, n);
    for(int opt, x, y, k, i = 1; i <= m; i++)
    {
        scanf("%d", &opt);
        if(opt == 1)
        {
            scanf("%d%d%d", &x, &y, &k);
            tree.update(1, 1, n, x, y, k);
        }
        else
        {
            scanf("%d", &x);
            printf("%d
", tree.query(1, 1, n, x));
        }
    }
    return 0;
}

线段树 区间修改 + 区间查询

用时 (9 space mathrm{min})

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

const LL N = 100100;
LL n, m, a[N], sum[N << 2], tag[N << 2];
struct Segment_Tree
{
    void push_up(LL x) { sum[x] = sum[x << 1] + sum[x << 1 | 1]; }
    void push_down(LL x, LL l, LL r)
    {
        LL mid = (l + r) >> 1;
        if(!tag[x]) return ;
        tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x];
        sum[x << 1] += (mid - l + 1) * tag[x];
        sum[x << 1 | 1] += (r - mid) * tag[x];
        tag[x] = 0;
    }
    void build(LL x, LL l, LL r)
    {
        if(l == r)
        {
            sum[x] = a[l];
            return ;
        }
        LL mid = (l + r) >> 1;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        push_down(x, l, r), push_up(x);
    }
    void update(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
    {
        if(l > stdr || r < stdl) return ;
        if(stdl <= l && stdr >= r)
        {
            tag[x] += k;
            sum[x] += (r - l + 1) * k;
            push_down(x, l, r);
            return ;
        }
        LL mid = (l + r) >> 1;
        push_down(x, l, r);
        update(x << 1, l, mid, stdl, stdr, k);
        update(x << 1 | 1, mid + 1, r, stdl, stdr, k);
        push_down(x, l, r), push_up(x);
    }
    LL query(LL x, LL l, LL r, LL stdl, LL stdr)
    {
        if(l > stdr || r < stdl) return 0;
        if(stdl <= l && stdr >= r) return sum[x];
        LL mid = (l + r) >> 1;
        push_down(x, l, r);
        return query(x << 1, l, mid, stdl, stdr) + 
        query(x << 1 | 1, mid + 1, r, stdl, stdr);
        push_up(x);
    }
} tree;

int main()
{
    scanf("%lld%lld", &n, &m);
    for(LL i = 1; i <= n; i++) scanf("%lld", &a[i]);
    tree.build(1, 1, n);
    for(LL opt, x, y, k, i = 1; i <= m; i++)
    {
        scanf("%lld", &opt);
        if(opt == 1)
        {
            scanf("%lld%lld%lld", &x, &y, &k);
            tree.update(1, 1, n, x, y, k);
        }
        else
        {
            scanf("%lld%lld", &x, &y);
            printf("%lld
", tree.query(1, 1, n, x, y));
        }
    }
    return 0;
}

线段树 区间乘法 + 区间加法

用时 (114514 space mathrm{min})

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;

const int N = 2333333;
LL n, m, p, a[N], sum[N], mul[N], add[N];

struct Segment_Tree
{
    void push_up(LL x) { sum[x] = (sum[x << 1] + sum[x << 1 | 1] + p) % p; }
    void push_down(LL x, LL l, LL r)
    {
        LL mid = (l + r) >> 1;
        mul[x << 1] = (mul[x << 1] * mul[x] + p) % p;
        mul[x << 1 | 1] = (mul[x << 1 | 1] * mul[x] + p) % p;
        add[x << 1] = (add[x << 1] * mul[x] + add[x] + p) % p;
        add[x << 1 | 1] = (add[x << 1 | 1] * mul[x] + add[x] + p) % p;
        sum[x << 1] = (sum[x << 1] * mul[x] + add[x] * (mid - l + 1) + p) % p;
        sum[x << 1 | 1] = (sum[x << 1 | 1] * mul[x] + add[x] * (r - mid) + p) % p;
        mul[x] = 1, add[x] = 0;
    } 
    void build(LL x, LL l, LL r)
    {
        add[x] = 0, mul[x] = 1;
        if(l == r)
        {
            sum[x] = (a[l] + p) % p;
            return ;
        }
        LL mid = (l + r) >> 1;
        build(x << 1, l, mid);
        build(x << 1 | 1, mid + 1, r);
        push_up(x);
    }
    void update1(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
    {
        if(l > stdr || r < stdl) return ;
        if(stdl <= l && stdr >= r)
        {
            mul[x] = (mul[x] * k + p) % p;
            add[x] = (add[x] * k + p) % p;
            sum[x] = (sum[x] * k + p) % p;
            push_down(x, l, r);
            return ;
        }
        LL mid = (l + r) >> 1;
        push_down(x, l, r);
        update1(x << 1, l, mid, stdl, stdr, k);
        update1(x << 1 | 1, mid + 1, r, stdl, stdr, k);
        push_down(x, l, r), push_up(x);
    }
    void update2(LL x, LL l, LL r, LL stdl, LL stdr, LL k)
    {
        if(l > stdr || r < stdl) return ;
        if(stdl <= l && stdr >= r)
        {
            add[x] = (add[x] + k + p) % p;
            sum[x] = (sum[x] + k * (r - l + 1) + p) % p;
            push_down(x, l, r);
            return ;
        }
        LL mid = (l + r) >> 1;
        push_down(x, l, r);
        update2(x << 1, l, mid, stdl, stdr, k);
        update2(x << 1 | 1, mid + 1, r, stdl, stdr, k);
        push_down(x, l, r), push_up(x);
    }
    LL query(LL x, LL l, LL r, LL stdl, LL stdr)
    {
        if(l > stdr || r < stdl) return 0;
        if(stdl <= l && stdr >= r) return (sum[x] + p) % p;
        LL mid = (l + r) >> 1;
        push_down(x, l, r);
        return (query(x << 1, l, mid, stdl, stdr) + 
        query(x << 1 | 1, mid + 1, r, stdl, stdr) + p) % p;
    }
} tree;

int main()
{
    scanf("%lld%lld%lld", &n, &m, &p);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    tree.build(1, 1, n);
    for(LL opt, x, y, k, i = 1; i <= m; i++)
    {
        scanf("%lld", &opt);
        if(opt == 1)
        {
            scanf("%lld%lld%lld", &x, &y, &k);
            tree.update1(1, 1, n, x, y, k);
        }
        else if(opt == 2)
        {
            scanf("%lld%lld%lld", &x, &y, &k);
            tree.update2(1, 1, n, x, y, k);
        }
        else
        {
            scanf("%lld%lld", &x, &y);
            printf("%lld
", tree.query(1, 1, n, x, y));
        }
    }
    return 0;
}

快速幂

int poww(int b, int p, int k)
{
    int ans = 1;
    while(p)
    {
        if(p & 1) ans = (ans * b) % k;
        b = (b * b) % k;
        p >>= 1;
    }
    return ans;
}

单调队列

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

const int N = 2333333;
long long n, k, head = 1, tail = 0, a[N], q[N];

int main()
{
    scanf("%lld%lld", &n, &k);
    memset(q, 0, sizeof(q));
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for(int i = 1; i <= n; i++)
    {
        while(head <= tail && q[head] <= i - k) head++;
        while(head <= tail && a[q[tail]] >= a[i]) tail--;
        q[++tail] = i;
        if(i >= k) printf("%lld ", a[q[head]]);
    }
    printf("
");
    head = 1, tail = 0, memset(q, 0, sizeof(q));
    for(int i = 1; i <= n; i++)
    {
        while(head <= tail && q[head] <= i - k) head++;
        while(head <= tail && a[q[tail]] <= a[i]) tail--;
        q[++tail] = i;
        if(i >= k) printf("%lld ", a[q[head]]);
    }
    return 0;
}

01 背包

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

const int N = 23333;
int t, n, w[N], v[N], f[N];

int main()
{
    scanf("%d%d", &t, &n);
    memset(f, 0, sizeof(f));
    for(int i = 1; i <= n; i++) scanf("%d%d", &w[i], &v[i]);
    for(int i = 1; i <= n; i++)
        for(int j = t; j >= w[i]; j--)
            f[j] = max(f[j], f[j - w[i]] + v[i]);
    printf("%d", f[t]);
    return 0;
}
原文地址:https://www.cnblogs.com/Andy-park/p/14077498.html