• 模板复习


    Hihocoder KMP

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 1000005;
    
    char s[maxn], T[maxn];
    int len_s, len_t, cnt, N;
    int nxt[maxn];
    
    void Getnxt(){
            nxt[0] = -1;
            int i = 0, t = -1;
            while(i < len_s)
                    if(t == -1 || s[i] == s[t]) nxt[++ i] = ++ t; //  "==" --> "!="
                    else t = nxt[t];
    }
    
    void KMP(){
            int t1 = 0, t2 = 0;
            while(t2 < len_t)
                    if(t1 == -1 || s[t1] == t[t2]){
                            t1 ++, t2 ++; 
                            if(t1 == len_s){ 
                                    t1 = nxt[t1]; 
                                    cnt ++;
                            }
                    }else t1 = nxt[t1];
    }
    
    void Work(){
            scanf("%s%s", s, T);
            len_s = strlen(s), len_t = strlen(T);
            Getnxt();
            cnt = 0;
            KMP();
            printf("%d
    ", cnt);
    }
    
    int main(){
            scanf("%d", &N);
            while(N --) Work();
            return 0;
    }
    

    Hihocoder #1077 : RMQ问题再临-线段树 线段树单点修改, 区间最小值

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 1e6 + 10;
    
    int N, M;
    int Ql, Qr;
    
    struct Node{
            int v, l, r, min_v;
    } T[maxn<<2];
    
    void Build(int k, int l, int r){
            T[k].l = l, T[k].r = r;
            if(l == r){
                    scanf("%d", &T[k].v), T[k].min_v = T[k].v;
                    return ;
            }
            int mid = l+r >> 1;
            Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
            T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
    }
    
    int Query(int k){
            int l = T[k].l, r = T[k].r;
            if(Ql <= l && r <= Qr) return T[k].min_v;
            int mid = l+r >> 1;
            if(mid < Ql) return Query(k<<1|1);
            else if(mid >= Qr) return Query(k<<1);
            return std::min(Query(k<<1|1), Query(k<<1));
    }
    
    void Modify(int k){
            int l = T[k].l, r = T[k].r;
            if(l == r){
                    T[k].min_v = T[k].v = Qr;
                    return ;
            }
            int mid = l+r >> 1;
            if(Ql <= mid) Modify(k<<1);
            else Modify(k<<1|1);
            T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
    }
    
    int main(){
            scanf("%d", &N);
            Build(1, 1, N);
            scanf("%d", &M);
            int opt;
            while(M --){
                    scanf("%d%d%d", &opt, &Ql, &Qr);
                    if(!opt){
                            int Ans = Query(1);
                            printf("%d
    ", Ans);
                    }
                    else Modify(1);
            }
            return 0;
    }
    

    P3372 【模板】线段树 1线段树区间修改, 区间和

    注意标记的加值

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 1e6 + 10;
    
    typedef long long ll;
    
    int N, M;
    int Ql, Qr;
    ll Qv;
    int tag[maxn<<2];
    
    struct Node{
            ll v, min_v, sum;
            int l, r;
    } T[maxn<<2];
    
    void Build(int k, int l, int r){
            T[k].l = l, T[k].r = r;
            if(l == r){
                    scanf("%lld", &T[k].v), T[k].min_v = T[k].v, T[k].sum = T[k].v;
                    return ;
            }
            int mid = l+r >> 1;
            Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
            T[k].min_v = std::min(T[k<<1].min_v, T[k<<1|1].min_v);
            T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
    }
    
    void Push_down(int k){
            int l, r;
            tag[k<<1] += tag[k], tag[k<<1|1] += tag[k];
            l = T[k<<1].l, r = T[k<<1].r;
            T[k<<1].sum += 1ll*(r - l + 1) * tag[k];
            l = T[k<<1|1].l, r = T[k<<1|1].r;
            T[k<<1|1].sum += 1ll*(r - l + 1) * tag[k];
            tag[k] = 0;
    }
    
    void Modify_2(int k){
            int l = T[k].l, r = T[k].r;
            if(Ql <= l && r <= Qr){
                    T[k].sum += 1ll*(r-l+1)*Qv;
                    tag[k] += Qv;
                    return ;
            }
            if(tag[k]) Push_down(k);
            int mid = l+r >> 1;
            if(mid < Ql) Modify_2(k<<1|1);
            else if(mid >= Qr) Modify_2(k<<1);
            else Modify_2(k<<1), Modify_2(k<<1|1);
            T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
    }
    
    ll Query_2(int k){
            int l = T[k].l, r = T[k].r;
            if(Ql <= l && r <= Qr) return T[k].sum;
            if(tag[k]) Push_down(k);
            ll tmp = 0;
            int mid = l+r >> 1;
            if(mid < Ql) tmp += Query_2(k<<1|1);
            else if(mid >= Qr) tmp += Query_2(k<<1);
            else tmp += Query_2(k<<1) + Query_2(k<<1|1);
            T[k].sum = T[k<<1].sum + T[k<<1|1].sum;
            return tmp;
    }
    
    int main(){
            scanf("%d%d", &N, &M);
            Build(1, 1, N);
            int opt;
            while(M --){
                    scanf("%d%d%d", &opt, &Ql, &Qr);
                    if(opt == 1){
                            scanf("%lld", &Qv);
                            Modify_2(1);
                    }else{
                            ll Ans = Query_2(1);
                            printf("%lld
    ", Ans);
                    }
            }
            return 0;
    }
    

    树链剖分

    注意Dfn序和原编号的区别

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 1e5+10;
    
    int N, M, R, P;
    int head[maxn], size[maxn], max_son[maxn], max_w[maxn];
    int top[maxn], dfn[maxn], Fa[maxn], dep[maxn], w[maxn], max_num[maxn];
    int tim, num0;
    
    namespace Seg{
    
            struct Node{
                    int v, l, r, tag;
            } T[maxn<<2];
    
            void Build(int k, int l, int r){
                    T[k].l = l, T[k].r = r;
                    if(l == r){
                            T[k].v = T[k].tag = 0;
                            return ;
                    }
                    int mid = l+r >> 1;
                    Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
                    T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
            }
    
            void Push_down(int k){
                    T[k<<1].tag = (1ll*T[k<<1].tag + T[k].tag) % P;
                    T[k<<1|1].tag = (1ll*T[k<<1|1].tag + T[k].tag) % P;
                    int l, r;
                    l = T[k<<1].l, r = T[k<<1].r;
                    T[k<<1].v = (1ll*T[k<<1].v + (1ll*T[k].tag*(r - l + 1) % P)) % P;
                    l = T[k<<1|1].l, r = T[k<<1|1].r;
                    T[k<<1|1].v = (1ll*T[k<<1|1].v + (1ll*T[k].tag*(r - l + 1) % P)) % P;
                    T[k].tag = 0;
            }
    
            void Modify(int k, const int &Ql, const int &Qr, const int &v){
                    int l = T[k].l, r = T[k].r;
                    if(Ql <= l && r <= Qr){
                            T[k].v += 1ll*v*(r - l + 1) % P;
                            T[k].tag = (1ll*T[k].tag + v) % P;
                            return ;
                    }
                    if(T[k].tag) Push_down(k);
                    int mid = l+r >> 1;
                    if(mid < Ql) Modify(k<<1|1, Ql, Qr, v);
                    else if(mid >= Qr) Modify(k<<1, Ql, Qr, v);
                    else Modify(k<<1, Ql, Qr, v), Modify(k<<1|1, Ql, Qr, v);
                    T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
            }
    
            int Query(int k, const int &Ql, const int &Qr){
                    int l = T[k].l, r = T[k].r;
                    if(Ql <= l && r <= Qr) return T[k].v;
                    if(T[k].tag) Push_down(k);
                    int mid = l+r >> 1;
                    T[k].v = (1ll*T[k<<1].v + T[k<<1|1].v) % P;
                    if(mid < Ql) return Query(k<<1|1, Ql, Qr);
                    else if(mid >= Qr) return Query(k<<1, Ql, Qr);
                    return (1ll*Query(k<<1|1, Ql, Qr) + Query(k<<1, Ql, Qr)) % P;
            }
    
    }
    
    struct Edge{ int nxt, to; } edge[maxn<<1];
    
    void Add(int from, int to){
            edge[++ num0] = (Edge){ head[from], to };
            head[from] = num0;
    }
    
    void DFS_1(int k, int fa){
            size[k] = 1;
            max_son[k] = 0, max_w[k] = 0;
            dep[k] = dep[fa] + 1;
            Fa[k] = fa;
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(to == fa) continue ;
                    DFS_1(to, k);
                    size[k] += size[to];
                    if(size[to] > max_w[k]){
                            max_w[k] = size[to];
                            max_son[k] = to;
                    }
            }
    }
    
    void DFS_2(int k, int fa){
            dfn[k] = ++ tim;
            Seg::Modify(1, dfn[k], dfn[k], w[k]);
            top[k] = fa;
            if(max_son[k]) DFS_2(max_son[k], fa);
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(dfn[to]) continue ;
                    DFS_2(to, to);
            }
            max_num[k] = tim;
    }
    
    void Modify_P(int x, int y, int z){
            while(top[x] != top[y]){
                    if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
                    Seg::Modify(1, dfn[top[x]], dfn[x], z);
                    x = Fa[top[x]];
            }
            if(dfn[x] > dfn[y]) std::swap(x, y);
            Seg::Modify(1, dfn[x], dfn[y], z);
    }
    
    int Query_P(int x, int y){
            int res = 0;
            while(top[x] != top[y]){
                    if(dep[top[x]] < dep[top[y]]) std::swap(x, y);
                    res = (1ll*res+Seg::Query(1, dfn[top[x]], dfn[x])) % P;
                    x = Fa[top[x]];
            }
            if(dfn[x] > dfn[y]) std::swap(x, y);
            res = (1l*res + Seg::Query(1, dfn[x], dfn[y])) % P;
            return res;
    }
    
    void Work(){
            int opt, x, y, z;
            scanf("%d", &opt);
            if(opt == 1){
                    scanf("%d%d%d", &x, &y, &z);
                    Modify_P(x, y, z);
            }else if(opt == 2){
                    scanf("%d%d", &x, &y);
                    int Ans = Query_P(x, y);
                    printf("%d
    ", Ans);
            }else if(opt == 3){
                    scanf("%d%d", &x, &z);
                    Seg::Modify(1, dfn[x], max_num[x], z);
            }else{
                    scanf("%d", &x);
                    int Ans = Seg::Query(1, dfn[x], max_num[x]);
                    printf("%d
    ", Ans);
            }
    }
    
    int main(){
            scanf("%d%d%d%d", &N, &M, &R, &P);
            int a, b;
            for(reg int i = 1; i <= N; i ++) scanf("%d", &w[i]);
            Seg::Build(1, 1, N);
            for(reg int i = 1; i < N; i ++){
                    scanf("%d%d", &a, &b);
                    Add(a, b), Add(b, a);
            }
            DFS_1(R, R);            // second  'R' --> '0'
            DFS_2(R, R);            // second  'R' --> '0'
            while(M --) Work();
            return 0;
    }
    
    

    普通平衡树

    > 和 < 的区别
    5个数组
    对一个节点进行操作后进行Splay
    前驱后继的操作注意特判

    int S_pre(int x, short opt){  // 1: su  0:  pre
            find(x);
            if(opt == 1){	//特判
                    if(key[rot] > x) return rot;
            }else if(key[rot] < x) return rot;
            int t = ch[rot][opt]; opt ^= 1;
            while(ch[t][opt]) t = ch[t][opt];
            return t;
    }
    

    插入的时候必须Splay
    注意赋值关系

    //AC
    int Kth(int t, int x){
            while(1){
                    if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0]; 
                    else if(size[ch[t][0]] + cnt[t] < x) x -= size[ch[t][0]] + cnt[t], t = ch[t][1];
                    else return t;
            }
    }
    //WA
    
    int Kth(int t, int x){
            while(1){
                    if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0]; 
                    else if(size[ch[t][0]] + cnt[t] < x)  t = ch[t][1], x -= size[ch[t][0]] + cnt[t];
                    else return t;
            }
    }
    
    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    
    int num0, rot;
    int cnt[maxn], size[maxn];
    int par[maxn], ch[maxn][2], key[maxn];
    
    inline void Push_up(int x){ size[x] = size[ch[x][0]] + size[ch[x][1]] + cnt[x]; }
    
    inline bool chk(int x){ return ch[par[x]][1] == x; }
    
    void rotate(int x){
            int y = par[x], z = par[y], d = chk(x), s = ch[x][d^1];
            ch[y][d] = s, par[s] = y;
            ch[z][chk(y)] = x, par[x] = z;
            ch[x][d^1] = y, par[y] = x;
            Push_up(y), Push_up(x);
    }
    
    void Splay(int x, int aim=0){
            while(par[x] != aim){
                    int y = par[x], z = par[y];
                    if(z != aim){
                            if(chk(x) == chk(y)) rotate(y);
                            else rotate(x);
                    }
                    rotate(x);
            }
            if(!aim) rot = x;
    }
    
    void Insert(int x){ //~~
            int t = rot, last = 0;
            while(t && key[t] != x){
                    last = t;
                    t = ch[t][key[t] < x];
            }
            if(t) cnt[t] ++;
            else{
                    key[t = ++ num0] = x;
                    if(last) ch[last][key[last] < x] = num0;
                    ch[num0][0] = ch[num0][1] = 0, size[num0] = 1;
                    par[num0] = last;
                    cnt[num0] = 1;
            }
            Splay(t);
    }
    
    void find(int x){
            if(!rot) return ;
            int t = rot;
            while(ch[t][key[t] < x] && key[t] != x) t = ch[t][key[t] < x];
            Splay(t);
    }
    
    int S_pre(int x, short opt){  // 1: su  0:  pre
            find(x);
            
            if(opt == 1){
                    if(key[rot] > x) return rot;
            }else if(key[rot] < x) return rot;
            
            int t = ch[rot][opt]; opt ^= 1;
            while(ch[t][opt]) t = ch[t][opt];
            return t;
    }
    
    void Remove(int x){
            int su = S_pre(x, 1), pre = S_pre(x, 0);
            Splay(pre), Splay(su, pre);
            int t = ch[su][0];
            if(cnt[t] == 1) ch[su][0] = 0;
            else cnt[t] --, Splay(t);   //~~
    }
    
    inline void Ask_1(int x){
            find(x);
            printf("%d
    ", size[ch[rot][0]]);
    }
    
    int Kth(int t, int x){
            while(1){
                    if(ch[t][0] && size[ch[t][0]] >= x) t = ch[t][0]; 
                    else if(size[ch[t][0]] + cnt[t] < x) x -= size[ch[t][0]] + cnt[t], t = ch[t][1];
                    else return t;
            }
    }
    
    inline void Ask_2(int x){
    //        printf("fuck: %d size: %d cnt %d
    ",rot, size[ch[rot][0]], cnt[rot]);  
            int t = Kth(rot, x);
            printf("%d
    ", key[t]);
    }
    
    void Work(){
            int opt, x;
            scanf("%d%d", &opt, &x);
            if(opt == 1) Insert(x);
            else if(opt == 2) Remove(x);
            else if(opt == 3) Ask_1(x);
            else if(opt == 4) Ask_2(x+1);
            else if(opt == 5) printf("%d
    ", key[S_pre(x, 0)]);
            else printf("%d
    ", key[S_pre(x, 1)]);
    }
    
    int main(){
            int N;
            scanf("%d", &N);
            Insert(0xcfcfcfcf), Insert(0x3f3f3f3f);
            for(reg int i = 1; i <= N; i ++) Work();
            return 0;
    }
    

    最大流

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    const int inf = 0x7f7f7f7f;
    
    int N, M, S, T, num0;
    int head[maxn], cur[maxn], dep[maxn];
    
    struct Edge{
            int nxt, to, dis, flow;
    } edge[maxn<<1];
    
    void Add(int from, int to, int Dis){
            edge[num0] = (Edge){ head[from], to, Dis, 0 };
            head[from] = num0 ++;
    }
    
    bool BFS(){
            memset(dep, -1, sizeof dep);
            for(reg int i = 0; i <= N; i ++) cur[i] = head[i];
            dep[S] = 1;
            std::queue <int> Q;
            Q.push(S);
            while(!Q.empty()){
                    int t = Q.front(); Q.pop();
                    for(reg int i = head[t]; ~i; i = edge[i].nxt){
                            int to = edge[i].to;
                            if(dep[to] == -1 && edge[i].dis > edge[i].flow){
                                    dep[to] = dep[t] + 1;
                                    Q.push(to);
                            }
                    }
            }
            return dep[T] != -1;
    }
    
    int DFS(int k, int W){
            if(k == T) return W;
            for(reg int &i = cur[k]; ~i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(dep[to] == dep[k] + 1 && edge[i].dis > edge[i].flow){
                            int tmp = DFS(to, std::min(W, edge[i].dis - edge[i].flow));
                            if(tmp){
                                    edge[i].flow += tmp;
                                    edge[i^1].flow -= tmp;
                                    return tmp;
                            }
                    }
            }
            return 0;
    }
    
    int Dinic(){
            int Ans = 0;
            while(BFS()){
                    while(int res = DFS(S, inf)) Ans += res;
            }
            return Ans;
    }
    
    int main(){
            scanf("%d%d%d%d", &N, &M, &S, &T);
            int x, y, z;
            memset(head, -1, sizeof head);
            for(reg int i = 1; i <= M; i ++){
                    scanf("%d%d%d", &x, &y, &z);
                    Add(x, y, z), Add(y, x, 0);
            }
            printf("%d
    ", Dinic());
            return 0;
    }
    /*
    memset(head, -1, sizeof head)
    
    void Add(int from, int to, int Dis){
            edge[num0] = (Edge){ head[from], to, Dis, 0 };
            head[from] = num0 ++;
    }
    
    */
    

    最小费用最大流

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 50005;
    
    int N, M, S, T, num0;
    int head[maxn];
    std::bitset <5005> Used;
    int Dis[5005], Flow[5005], Pre[5005], Pre_1[5005];
    
    struct Edge{
            int nxt, to, dis, flow, cost;
    } edge[maxn << 1];
    
    void Add(int from, int to, int dis, int cost){
            edge[num0] = (Edge){ head[from], to, dis, 0, cost };
            head[from] = num0 ++;
    }
    
    int Spfa(){
            memset(Dis, 0x3f, sizeof Dis);
            memset(Flow, 0x3f, sizeof Flow);
            Used.reset();
            std::queue <int> Q;
            Q.push(S), Dis[S] = 0, Used.set(S, 1);
            while(!Q.empty()){
                    int t = Q.front(); Q.pop();
                    //printf("fuck %d
    ", t);
                    Used.set(t, 0);
                    for(reg int i = head[t]; ~i; i = edge[i].nxt){
                            int to = edge[i].to;
                            if(Dis[to] > Dis[t] + edge[i].cost && edge[i].dis > edge[i].flow){
                                    Dis[to] = Dis[t] + edge[i].cost;
                                    Pre[to] = t;
                                    Pre_1[to] = i;
                                    Flow[to] = std::min(Flow[t], edge[i].dis - edge[i].flow);
                                    if(!Used.test(to)){
                                            Used.set(to, 1); Q.push(to);
                                    }
                            }
                    }
            }
            return Flow[T];
    }
    
    int MFMS(){
            int Ans = 0, res = 0, Ans_2 = 0;
            while((res = Spfa()) != 0x3f3f3f3f){
                    Ans += res;
                    Ans_2 += Dis[T] * Flow[T];
                    int t = T;
                    while(t != S){
                            int tmp = Pre_1[t];
                            edge[tmp].flow += res;
                            edge[tmp^1].flow -= res;
                            t = Pre[t];
                    }
            }
            printf("%d ", Ans);
            return Ans_2;
    }
    
    int main(){
    //        freopen("test.in", "r", stdin);
            scanf("%d%d%d%d", &N, &M, &S, &T);
            memset(head, -1, sizeof head);
            for(reg int i = 1; i <= M; i ++){
                    int x, y, z, w;
                    scanf("%d%d%d%d", &x, &y, &z, &w);
                    Add(x, y, z, w), Add(y, x, 0, -w);
            }
            printf("%d
    ", MFMS());
            return 0;
    }
    /*
    Add(x, y, z, w), Add(y, x, 0, -w);
    
    if(Dis[to] > Dis[t] + edge[i].cost && edge[i].dis > edge[i].flow){
            
    */
    
  • 相关阅读:
    java集合Collection常用方法详解
    JavaWeb_cookie和session
    JavaWeb_Cookie
    Java中双向链表
    Java链表基础
    select函数详解及实例分析
    socket select函数的详细讲解
    记录远程用户登录日志
    MSSQL grant
    dll 中使用ADO
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822647.html
Copyright © 2020-2023  润新知