zoukankan      html  css  js  c++  java
  • 存一些东西

    @

    头文件

    #pragma comment(linker, "/STACK:102400000,102400000")
    //#include<bits/stdc++.h>
    #include <ctime>
    #include <iostream>
    #include <assert.h>
    #include <vector>
    #include <queue>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define fi first
    #define se second
    #define endl '
    '
    #define o2(x) (x)*(x)
    #define BASE_MAX 31
    #define mk make_pair
    #define eb push_back
    #define SZ(x) ((int)(x).size())
    #define all(x) (x).begin(), (x).end()
    #define clr(a, b) memset((a),(b),sizeof((a)))
    #define iis std::ios::sync_with_stdio(false); cin.tie(0)
    #define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
    using namespace std;
    #pragma optimize("-O3")
    typedef long long LL;
    typedef unsigned long long uLL;
    typedef pair<int, int> pii;
    inline LL read() {
        LL x = 0;int f = 0;
        char ch = getchar();
        while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
        while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x = f ? -x : x;
    }
    inline void write(LL x, bool f) {
        if (x == 0) {putchar('0'); if(f)putchar('
    ');else putchar(' ');return;}
        if (x < 0) {putchar('-');x = -x;}
        static char s[23];
        int l = 0;
        while (x != 0)s[l++] = x % 10 + 48, x /= 10;
        while (l)putchar(s[--l]);
        if(f)putchar('
    ');else putchar(' ');
    }
    int lowbit(int x) { return x & (-x); }
    template<class T>T big(const T &a1, const T &a2) { return a1 > a2 ? a1 : a2; }
    template<class T>T sml(const T &a1, const T &a2) { return a1 < a2 ? a1 : a2; }
    template<typename T, typename ...R>T big(const T &f, const R &...r) { return big(f, big(r...)); }
    template<typename T, typename ...R>T sml(const T &f, const R &...r) { return sml(f, sml(r...)); }
    void debug_out() { cerr << '
    '; }
    template<typename T, typename ...R>void debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);}
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
    
    
    const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
    const int HMOD[] = {1000000009, 1004535809};
    const LL BASE[] = {1572872831, 1971536491};
    const int mod = 1e7 + 7;
    const int MOD = 1e7 + 7;//998244353
    const int INF = 0x3f3f3f3f;
    
    #ifndef ONLINE_JUDGE
        freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
        //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
    #endif
    

    线性基

    线性基交:牛客2019多校第四场B题

    struct Base {
        int b[BASE_MAX + 1];
        int& operator [](int x) {
            return b[x];
        }
        int operator [](int x)const {
            return b[x];
        }
        void clear(int f) {
            if(f == 0) memset(b, 0, sizeof(int)*(BASE_MAX+1));
            else {
                for(int i = 0; i <= BASE_MAX; ++i) b[i] = (1<<i);
            }
        }
        bool check(int x) {
            for(int i = BASE_MAX; i >= 0; --i) {
                if(x & (1 << i)) x ^= b[i];
            }
            return (x == 0);
        }
        void out() {
            for(int i = 0; i <= BASE_MAX; ++i) printf("%d ", b[i]);
            printf("
    ");
        }
    }bs[MXN];
    bool insert(int x, int *bs) {
        for(int j = BASE_MAX; j >= 0; --j) {
            if(!(x >> j)) continue;
            if(bs[j]) x ^= bs[j];
            else {
                bs[j] = x;
                for(int k = j-1; k >= 0; --k) if(bs[k]&&(bs[j]&(1LL<<k))) bs[j]^=bs[k];
                for(int k = j+1; k <= BASE_MAX; ++k) if(bs[k]&(1LL<<j)) bs[k]^=bs[j];
                return true;
            }
        }
        return false;
    }
    Base merge(const Base&a, const Base&b) {//600ms
        Base c = b, d = b, rt = {};
        for(int i = 0; i <= BASE_MAX; ++i) assert(rt[i] == 0);
        for (int i = 0, x; i <= BASE_MAX; ++i) {
            x = a[i];
            if (!x)continue;
            int j = i, T = 0;
            for (; j >= 0; --j) {
                if ((x >> j) & 1)
                    if (c[j]) { x ^= c[j]; T ^= d[j]; }
                    else break;
            }
            if (!x) rt[i] = T;
            else { c[j] = x; d[j] = T; }
        }
        return rt;
    }
    Base merge1(const Base&a, const Base&b) {//400ms
        int cur, d;
        Base tot = a, na = a, rt = {};
        for(int i = 0; i <= BASE_MAX; ++i) assert(rt[i] == 0);
        for(int i = 0; i <= BASE_MAX; ++i) if(b[i]) {
                cur = 0, d = b[i];
                for(int j = i; j >= 0; --j) if(d >> j & 1) {
                        if(tot[j]) {
                            d ^= tot[j], cur ^= na[j];
                            if(d == 0) { rt[i] = cur; break; }
                        } else {
                            tot[j] = d;
                            na[j] = cur;
                            break;
                        }
                    }
            }
        return rt;
    }
    

    单调栈/单调队列相关

    • 单调栈就是用一个栈实现的,可以求左/右边第一个大于/小于他的数字。(笛卡尔树是单调栈升级版)
    • 单调队列用一个双端队列实现,可以头指针和尾指针同时右移。可以保证这个区间内最大/小值位于左端点。
    • 单调栈:我是新来的,都得让着我
    • 单调队列:事已至此,不得不心狠手辣
      2019牛客第三场F题
    //类似与求区间最大最小值差小于等于q的区间数量
    void solve(int len) {
    //    clr(dq1, 0), clr(dq2, 0);
        head1 = tail1 = head2 = tail2 = 0;
        int tmp = 0;
        for(int i = 1; i <= n; ++i) {
            while(head1 < tail1 && Max[i] > Max[dq1[tail1]]) -- tail1;
            while(head2 < tail2 && Min[i] < Min[dq2[tail2]]) -- tail2;
            dq1[++tail1] = i, dq2[++tail2] = i;
    //        debug(head1, tail1, head1, tail2)
            while(head1 < tail1 && head2 < tail2 && Max[dq1[head1 + 1]] - Min[dq2[head2 + 1]] > q) {
                if(dq1[head1+1] < dq2[head2+1]) tmp = dq1[++head1];
                else tmp = dq2[++head2];
            }
            ans = big(ans, (i - tmp) * len);
    //        debug(len, tmp, i)
        }
    }
    

    树分治

    点分治

    裸题:poj1741
    分治的复杂度是较为稳定的(O(nlog(n)))
    静态点分治还是比较简单吧,按重心分治,每次能让子树大小减少一半以上,所以分治层数至多(log(n))层,这也是他复杂度稳定的一个原因吧。
    每递归一层都要重新求一次该子树的重心,因为每次把重新标记为1了,所以各子树间也不会互相有影响。
    后面动态点分治也是在此基础上建立的,感觉动态点分治利用了把重心连成一棵高度均衡(log(n))层的树(点分树?),然后使得一些复杂度看似不太对的暴力,成为了可行解。
    复杂度:(O(nlog(n)^2))

    const int MXN = 2e4 + 7;
    const int MXE = 4e4 + 7;
    int n, m;
    int tn;
    struct lp{
        int v, nex;
        int w;
    }cw[MXE];
    int tot, head[MXN], dep[MXN], siz[MXN], hvy, hvysiz, vis[MXN];
    int stak[MXN];
    LL ans;
    void add_edge(int a, int b, int c) {
        cw[++ tot].v = b, cw[tot].nex = head[a], cw[tot].w = c;
        head[a] = tot;
        cw[++ tot].v = a, cw[tot].nex = head[b], cw[tot].w = c;
        head[b] = tot;
    }
    void dfs_pre(int u, int ba) {
        int mm = 0;
        siz[u] = 1;
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_pre(v, u);
            siz[u] += siz[v];
            mm = big(mm, siz[v]);
        }
        mm = big(mm, tn - siz[u]);
        if(hvy == -1 || (mm < hvysiz)) {
            hvy = u;
            hvysiz = mm;
        }
    }
    void get_dep(int u, int ba) {
        stak[++ stak[0]] = dep[u];
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dep[v] = dep[u] + cw[i].w;
            get_dep(v, u);
        }
    }
    void get_ans(int u, int w, int flag) {
        stak[0] = 0;
        dep[u] = w;
        get_dep(u, u);
        sort(stak + 1, stak + 1 + stak[0]);
        for(int i = 1, j = stak[0]; i <= stak[0]; ++i) {
            while(j > i && stak[i] + stak[j] > m) -- j;
            ans += flag * big(0, j - i);
        }
    //    printf("%d :
    ", u);
    //    for(int i = 1; i <= stak[0]; ++i) printf("%d ", stak[i]);
    //    printf("
    ");
    }
    void dfs_dian(int u, int ba) {
        vis[u] = 1;
        get_ans(u, 0, 1);
    //    printf("%d %lld
    ", u, ans);
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            get_ans(v, cw[i].w, -1);
            tn = siz[v];
            hvy = hvysiz = -1;
            dfs_pre(v, u);
            dfs_dian(hvy ,0);
        }
    }
    int main() {
        while(~scanf("%d%d", &n, &m) && (n + m)) {
            for(int i = 1; i <= n; ++i) head[i] = -1, vis[i] = 0;
            tot = -1;
            for(int i = 1, a, b, c; i < n; ++i) {
                scanf("%d%d%d", &a, &b, &c);
                add_edge(a, b, c);
            }
            ans = 0;
            tn = n;
            hvy = hvysiz = -1;
            dfs_pre(1, 0);
            dfs_dian(hvy, 0);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    边分治

    裸题:poj1741
    普通的边分治复杂度极不稳定,参考菊花图。边分治复杂度主要决定因素是点的度数。
    解决方法是在不影响求解答案的前提下,重构图。让每个点度数至多为(3),又因为你至多会增加(n)个点,所以重构图之后边分治复杂度也是比较稳定的,可能常数会比较大吧。
    边分治重建树时有两种重建的方法,一种是构建成类线段树结构(高度均衡),一种是每出现两个点就新建一个点。
    法1用vector写比较方便,法2可以不用vector实现(法2有个优化就是让原节点连接一个虚节点和原儿子节点,而不是直接连接一个虚节点)。
    老年poj上面法1:500ms,法2:300ms。点分治:200ms。
    感觉我边分治写法常数应该巨大无比才对啊,为啥还能不到300ms的。。
    复杂度:(O(nlog(n)^2))

    //类线段树重建图 500ms
    const int MXN = 3e4 + 7;
    const int MXE = 6e4 + 7;
    int n, m;
    int tn;
    struct lp{
        int v, nex;
        int w, u;
    }cw[MXE];
    int tot, head[MXN], siz[MXN], hvy, hvysiz, vis[MXE];
    int stkl[MXN], stkr[MXN], suml[MXN], sumr[MXN], id[MXN], sdl[MXN], sdr[MXN], sum[MXN];
    vector<pii > vs[MXN];
    LL ans;
    void add_edge(int a, int b, int c) {
        cw[++ tot].v = b, cw[tot].nex = head[a], cw[tot].w = c, cw[tot].u = a;
        head[a] = tot;
        cw[++ tot].v = a, cw[tot].nex = head[b], cw[tot].w = c, cw[tot].u = b;
        head[b] = tot;
    }
    void dfs_pre(int u, int ba, int _tn) {
        siz[u] = 1;
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[i] || vis[i^1]) continue;
            dfs_pre(v, u, _tn);
            siz[u] += siz[v];
            if(hvy == -1 || big(hvysiz, _tn - hvysiz) > big(siz[v], _tn - siz[v])) {
                hvy = i;
                hvysiz = siz[v];
            }
        }
    }
    void dfs_dep(int f, int u, int ba, int w) {
        if(f) stkl[++stkl[0]] = w, suml[stkl[0]] = id[u];
        else stkr[++stkr[0]] = w, sumr[stkr[0]] = id[u];
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[i] || vis[i^1]) continue;
            dfs_dep(f, v, u, w + cw[i].w);
        }
    }
    bool cmpl(const int&a, const int&b) {
        return stkl[a] < stkl[b];
    }
    bool cmpr(const int&a, const int&b) {
        return stkr[a] < stkr[b];
    }
    void dfs_ans(int u, int _n) {
        if(_n <= 1) return;
        hvy = hvysiz = -1;
        dfs_pre(u, 0, _n);
    //    printf("--%d %d %d %d
    ", u, hvysiz, cw[hvy].u, cw[hvy].v);
        int tmphvy = hvy, tmpsiz = hvysiz;
        vis[tmphvy] = vis[tmphvy^1] = 1;
        stkl[0] = stkr[0] = 0;
        dfs_dep(1, cw[tmphvy].u, -1, 0), dfs_dep(0, cw[tmphvy].v, -1, 0);
        for(int i = 1; i <= stkl[0]; ++i) sdl[i] = i;
    //    for(int i = 1; i <= stkl[0]; ++i) printf("%d ", stkl[i]);
    //    printf("
    ");
    //    for(int i = 1; i <= stkl[0]; ++i) printf("%d ", suml[i]);
    //    printf("
    ");
        for(int i = 1; i <= stkr[0]; ++i) sdr[i] = i;
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", sumr[i]);
    //    printf("
    ");
        sort(sdl + 1, sdl + stkl[0] + 1, cmpl), sort(sdr + 1, sdr + stkr[0] + 1, cmpr);
        for(int i = 1; i <= stkr[0]; ++i) sum[i] = sum[i-1] + sumr[sdr[i]];
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", sum[i]);
    //    printf("
    ");
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", stkr[sdr[i]]);
    //    printf("
    ");
    //    sort(stkl + 1, stkl + 1 + stkl[0]), sort(stkr + 1, stkr + 1 + stkr[0]);
        for(int i = 1, j = stkr[0]; i <= stkl[0]; ++i) {
    //        printf("%d ", stkl[sdl[i]]);
            while(j >= 1 && stkl[sdl[i]] + cw[tmphvy].w + stkr[sdr[j]] > m) -- j;
            if(suml[sdl[i]]) ans += big(0, sum[j]);
        }
    //    printf("
    [%d]
    ", ans);
        dfs_ans(cw[tmphvy].u, _n - tmpsiz), dfs_ans(cw[tmphvy].v, tmpsiz);
    }
    void redfs(int u, int ba) {
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba) continue;
            redfs(v, u);
            vs[u].eb(mk(v, cw[i].w));
        }
    }
    void rebuild() {
        redfs(1, 0);
        tot = -1;
        for(int i = 1; i <= n + n; ++i) head[i] = -1;
        for(int i = 1, tx, ty; i <= n; ++i) {
            if(SZ(vs[i]) <= 2) {
                for(int j = 0; j < SZ(vs[i]); ++j) add_edge(i, vs[i][j].fi, vs[i][j].se);
            }else if(SZ(vs[i]) > 2) {
                tx = ++ n, ty = ++ n;
                add_edge(i, tx, 0), add_edge(i, ty, 0);
                for(int j = 0; j < SZ(vs[i]); ++j) {
                    if(j & 1) vs[ty].eb(vs[i][j]);
                    else vs[tx].eb(vs[i][j]);
                }
            }
        }
    }
    void dfs(int u, int ba) {
        for(int i = head[u]; ~i; i = cw[i].nex) {
            if(cw[i].v == ba) continue;
            printf("*%d %d %d %d
    ", cw[i].v, u, id[u], cw[i].w);
            dfs(cw[i].v, u);
        }
    }
    int main() {
        while(~scanf("%d%d", &n, &m) && (n + m)) {
            for(int i = 1; i <= n; ++i) head[i] = -1, id[i] = 1;
            tot = -1;
            for(int i = 1, a, b, c; i < n; ++i) {
                scanf("%d%d%d", &a, &b, &c);
                add_edge(a, b, c);
            }
            tn = tot;
            rebuild();
    //        dfs(1, 0);
            ans = 0;
            dfs_ans(1, n);
            printf("%lld
    ", ans);
            for(int i = 0; i <= tot; ++i)  vis[i] = 0;
            for(int i = 0; i <= n; ++i) vs[i].clear(), id[i] = 0;
        }
        return 0;
    }
    
    //暴力二叉树建图(一个和原节点对应一个虚节点 300ms
    const int MXN = 3e4 + 7;
    const int MXE = 6e4 + 7;
    int n, m;
    struct lp{
        int v, nex;
        int w, u;
    } cw2[MXE];
    int tot2, head2[MXN];
    int tot, head[MXN], siz[MXN], hvy, hvysiz, vis[MXE];
    int stkl[MXN], stkr[MXN], suml[MXN], sumr[MXN], id[MXN], sdl[MXN], sdr[MXN], sum[MXN];
    LL ans;
    void add_edge2(int a, int b, int c) {
        cw2[++ tot2].v = b, cw2[tot2].nex = head2[a], cw2[tot2].w = c, cw2[tot2].u = a;
        head2[a] = tot2;
        cw2[++ tot2].v = a, cw2[tot2].nex = head2[b], cw2[tot2].w = c, cw2[tot2].u = b;
        head2[b] = tot2;
    }
    void dfs_pre(int u, int ba, int _tn) {
        siz[u] = 1;
        for(int i = head2[u], v; ~i; i = cw2[i].nex) {
            v = cw2[i].v;
            if(v == ba || vis[i] || vis[i^1]) continue;
            dfs_pre(v, u, _tn);
            siz[u] += siz[v];
            if(hvy == -1 || big(hvysiz, _tn - hvysiz) > big(siz[v], _tn - siz[v])) {
                hvy = i;
                hvysiz = siz[v];
            }
        }
    }
    void dfs_dep(int f, int u, int ba, int w) {
        if(f) stkl[++stkl[0]] = w, suml[stkl[0]] = id[u];
        else stkr[++stkr[0]] = w, sumr[stkr[0]] = id[u];
        for(int i = head2[u], v; ~i; i = cw2[i].nex) {
            v = cw2[i].v;
            if(v == ba || vis[i] || vis[i^1]) continue;
            dfs_dep(f, v, u, w + cw2[i].w);
        }
    }
    bool cmpl(const int&a, const int&b) {
        return stkl[a] < stkl[b];
    }
    bool cmpr(const int&a, const int&b) {
        return stkr[a] < stkr[b];
    }
    void dfs_ans(int u, int _n) {
        if(_n <= 1) return;
        hvy = hvysiz = -1;
        dfs_pre(u, 0, _n);
    //    printf("--%d %d %d %d
    ", u, hvysiz, cw[hvy].u, cw[hvy].v);
        int tmphvy = hvy, tmpsiz = hvysiz;
        vis[tmphvy] = vis[tmphvy^1] = 1;
        stkl[0] = stkr[0] = 0;
        dfs_dep(1, cw2[tmphvy].u, -1, 0), dfs_dep(0, cw2[tmphvy].v, -1, 0);
        for(int i = 1; i <= stkl[0]; ++i) sdl[i] = i;
    //    for(int i = 1; i <= stkl[0]; ++i) printf("%d ", stkl[i]);
    //    printf("
    ");
    //    for(int i = 1; i <= stkl[0]; ++i) printf("%d ", suml[i]);
    //    printf("
    ");
        for(int i = 1; i <= stkr[0]; ++i) sdr[i] = i;
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", sumr[i]);
    //    printf("
    ");
        sort(sdl + 1, sdl + stkl[0] + 1, cmpl), sort(sdr + 1, sdr + stkr[0] + 1, cmpr);
        for(int i = 1; i <= stkr[0]; ++i) sum[i] = sum[i-1] + sumr[sdr[i]];
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", sum[i]);
    //    printf("
    ");
    //    for(int i = 1; i <= stkr[0]; ++i) printf("%d ", stkr[sdr[i]]);
    //    printf("
    ");
    //    sort(stkl + 1, stkl + 1 + stkl[0]), sort(stkr + 1, stkr + 1 + stkr[0]);
        for(int i = 1, j = stkr[0]; i <= stkl[0]; ++i) {
    //        printf("%d ", stkl[sdl[i]]);
            while(j >= 1 && stkl[sdl[i]] + cw2[tmphvy].w + stkr[sdr[j]] > m) -- j;
            if(suml[sdl[i]]) ans += big(0, sum[j]);
        }
    //    printf("
    [%d]
    ", ans);
        dfs_ans(cw2[tmphvy].u, _n - tmpsiz), dfs_ans(cw2[tmphvy].v, tmpsiz);
    }
    
    lp cw[MXE];
    void add_edge(int a, int b, int c) {
        cw[++ tot].v = b, cw[tot].nex = head[a], cw[tot].w = c, cw[tot].u = a;
        head[a] = tot;
        cw[++ tot].v = a, cw[tot].nex = head[b], cw[tot].w = c, cw[tot].u = b;
        head[b] = tot;
    }
    vector<pii> vs;
    void redfs(int u, int ba) {
        vs.clear();
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba) continue;
            vs.eb(mk(cw[i].v, cw[i].w));
        }
        if(SZ(vs) <= 2) {
            for(int i = 0; i < SZ(vs); ++i) add_edge2(u, vs[i].fi, vs[i].se);
        }else {
            int lst = -1;
            for(int i = 1; i < SZ(vs); ++i) {
                if(i == SZ(vs) - 1) {
                    add_edge2(u, lst, 0);
                    add_edge2(u, vs[i].fi, vs[i].se);
                }else if(i == 1) {
                    lst = ++ n;
                    add_edge2(lst, vs[i-1].fi, vs[i-1].se);
                    add_edge2(lst, vs[i].fi, vs[i].se);
                }else {
                    add_edge2(n + 1, lst, 0);
                    add_edge2(n + 1, vs[i].fi, vs[i].se);
                    lst = ++ n;
                }
            }
        }
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba) continue;
            redfs(v, u);
        }
    }
    void rebuild() {
        tot2 = -1;
        for(int i = 1; i <= n + n; ++i) head2[i] = -1;
        redfs(1, 0);
    }
    void dfs(int u, int ba) {
    //    cerr << u << " " << ba << endl;
        for(int i = head2[u]; ~i; i = cw2[i].nex) {
            if(cw2[i].v == ba) continue;
    //        printf("*%d %d %d %d
    ", cw2[i].v, u, id[u], cw2[i].w);
            dfs(cw2[i].v, u);
        }
    }
    int main() {
        while(~scanf("%d%d", &n, &m) && (n + m)) {
            for(int i = 1; i <= n; ++i) head[i] = -1, id[i] = 1;
            tot = -1;
            for(int i = 1, a, b, c; i < n; ++i) {
                scanf("%d%d%d", &a, &b, &c);
                add_edge(a, b, c);
            }
            rebuild();
            ans = 0;
            dfs_ans(1, n);
            printf("%lld
    ", ans);
            for(int i = 0; i <= tot2; ++i)  vis[i] = 0;
            for(int i = 0; i <= n; ++i) id[i] = 0;
        }
        return 0;
    }
    

    动态点分治(点分树)

    裸题:洛谷P2056(ZJOI2007)捉迷藏, BZOJ3730震波
    题目:CF757G , CF100633D
    感觉动态点分治利用点分树的特性使得看似暴力的解法变得合理。毕竟点分树层数在(log(n))级别。

    洛谷p2056这道裸题来说:
    对每个点维护其在点分树上子树内所有点到它父亲节点的距离信息,和该节点在点分树上每个子节点的所在子树内离他最远的距离(距离信息只需要最远和次远的即可,参考别人用优先队列封装了一个堆)
    每次更新就暴力沿着点分树向上更新即可。
    复杂度:(O(nlog(n)^2))

    const int MXN = 2e5 + 7;
    const int MXE = 2e6 + 7;
    int n, m;
    struct lp {
        int v, nex;
        int w;
    } cw[MXE];
    int tot, head[MXN], siz[MXN], hvy, hvysiz, vis[MXE];
    int col[MXN], dep[MXN], fa[MXN], dis[MXN][20];
    namespace LCA {
        int dis[MXN], up[MXN][20];
        void dfs(int u, int ba, int d) {
            up[u][0] = ba; dis[u] = d;
            for(int i = 1; i < 20; ++i) up[u][i] = up[up[u][i-1]][i-1];
            for(int i = head[u], v; ~i; i = cw[i].nex) {
                v = cw[i].v;
                if(v == ba) continue;
                dfs(v, u, d + 1);
            }
        }
        int lca(int x, int y) {
            if(dis[x] < dis[y]) swap(x, y);
            for(int i = 19; i >= 0; --i) {
                if(dis[up[x][i]] >= dis[y]) {
                    x = up[x][i];
                }
            }
            if(x == y) return x;
            for(int i = 19; i >= 0; --i) {
                if(up[x][i] != up[y][i]) {
                    x = up[x][i], y = up[y][i];
                }
            }
            return up[x][0];
        }
        int query(int i, int j) {
            return dis[i] + dis[j] - 2 * dis[lca(i, j)];
        }
    }
    struct heap {
        priority_queue<int> A, B;  // heap=A-B
        void insert(int x) { A.push(x); }
        void erase(int x) { B.push(x); }
        int top() {
            while (!B.empty() && A.top() == B.top()) A.pop(), B.pop();
            return A.top();
        }
        void pop() {
            while (!B.empty() && A.top() == B.top()) A.pop(), B.pop();
            A.pop();
        }
        int top2() {
            int t = top(), ret;
            pop();
            ret = top();
            A.push(t);
            return ret;
        }
        int size() { return A.size() - B.size(); }
    } disf[MXN], dison[MXN], ans;
    void add_edge(int a, int b) {
        cw[++ tot].v = b, cw[tot].nex = head[a];
        head[a] = tot;
        cw[++ tot].v = a, cw[tot].nex = head[b];
        head[b] = tot;
    }
    int get_dis(int i, int j) {
        if(i == j) return 0;
        if(dis[i][dep[i] - dep[j]]) return dis[i][dep[i] - dep[j]];
        dis[i][dep[i] - dep[j]] = LCA::query(i, j);
        return dis[i][dep[i] - dep[j]];
    }
    void dfs_pre(int u, int ba, int _tn) {
        int mm = 0;
        siz[u] = 1;
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_pre(v, u, _tn);
            siz[u] += siz[v];
            mm = big(mm, siz[v]);
        }
        mm = big(mm, _tn - siz[u]);
        if(hvy == -1 || hvysiz > mm) {
            hvy = u;
            hvysiz = mm;
        }
    }
    void dfs_dis(int u, int ba, int d, int rt) {
        disf[rt].insert(d);
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_dis(v, u, d + 1, rt);
        }
    }
    void dfs_get(int u, int _n, int f) {
        if(f) hvy = hvysiz = -1;
        else assert(hvy == u);
        if(f) dfs_pre(u, -1, _n);
    //    debug(u, _n, hvy)
        int lstrt = hvy;
        vis[lstrt] = 1;
        for(int i = head[lstrt], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == lstrt || vis[v]) continue;
            hvy = hvysiz = -1;
            dfs_pre(v, -1, siz[v]);
            dfs_dis(v, -1, 1, hvy);
            fa[hvy] = lstrt;
            dep[hvy] = dep[lstrt] + 1;
    //        debug(hvy, dep[hvy])
            dison[lstrt].insert(disf[hvy].top());
            dfs_get(hvy, siz[v], 0);
        }
        if(SZ(dison[lstrt]) >= 2) {
            ans.insert(dison[lstrt].top() + dison[lstrt].top2());
        }else if(SZ(dison[lstrt]))ans.insert(dison[lstrt].top());
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
        //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
    #endif
        n = read();
        for(int i = 1; i <= n; ++i) head[i] = -1;
        tot = -1;
        for(int i = 1, a, b; i < n; ++i) {
            a = read(), b = read();
            add_edge(a, b);
        }
        LCA::dfs(1, 0, 1);
        dfs_get(1, n, 1);
        m = read();
    //    debug(m, get_dis(1, 3), dep[1], dep[3])
        char op[3];
        int x, cnt = n;
        while(m --) {
            scanf("%s", op);
            if(op[0] == 'G') {
                if(cnt == 0) printf("-1
    ");
                else if(cnt == 1) printf("0
    ");
                else printf("%d
    ", ans.top());
            }else {
                x = read();
                if(col[x] == 0) {
                    if(SZ(dison[x]) == 1) ans.erase(dison[x].top());
                    for(int i = x; fa[i]; i = fa[i]) {
                        if(SZ(dison[fa[i]]) >= 2) ans.erase(dison[fa[i]].top() + dison[fa[i]].top2());
                        else if(col[fa[i]] == 0 && SZ(dison[fa[i]]) == 1) ans.erase(dison[fa[i]].top());
                        dison[fa[i]].erase(disf[i].top());
                        disf[i].erase(get_dis(x, fa[i]));
                        if(disf[i].size()) dison[fa[i]].insert(disf[i].top());
                        if(SZ(dison[fa[i]]) >= 2) ans.insert(dison[fa[i]].top() + dison[fa[i]].top2());
                        else if(col[fa[i]] == 0 &&SZ(dison[fa[i]])) ans.insert(dison[fa[i]].top());
                    }
                    col[x] = 1;
                    -- cnt;
                }else {
                    if(SZ(dison[x]) == 1) ans.insert(dison[x].top());
                    for(int i = x; fa[i]; i = fa[i]) {
                        if(SZ(dison[fa[i]]) >= 2) ans.erase(dison[fa[i]].top() + dison[fa[i]].top2());
                        else if(col[fa[i]] == 0 &&SZ(dison[fa[i]]) == 1) ans.erase(dison[fa[i]].top());
                        if(SZ(disf[i])) dison[fa[i]].erase(disf[i].top());
                        disf[i].insert(get_dis(x, fa[i]));
                        dison[fa[i]].insert(disf[i].top());
                        if(SZ(dison[fa[i]]) >= 2) ans.insert(dison[fa[i]].top() + dison[fa[i]].top2());
                        else if(col[fa[i]] == 0 &&SZ(dison[fa[i]])) ans.insert(dison[fa[i]].top());
                    }
                    col[x] = 0;
                    ++ cnt;
                }
            }
        }
    #ifndef ONLINE_JUDGE
        cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
    #endif
        return 0;
    }
    
    /*
     * http://wiki.gyh.me/DP/%E6%A0%91%E5%88%86%E6%B2%BB/
     */
    

    bzoj3730震波
    疯狂tle,好像网上动态点分治的代码全都过不了。。

    const int MXN = 2e5 + 7;
    const int MXE = 2e5 + 7;
    int n, m;
    const int N = 100002;
    struct lp {
        int v, nex;
        int w;
    } cw[MXE];
    int tot, head[MXN], siz[MXN], hvy, hvysiz;
    bool vis[MXN];
    int ar[MXN], dep[MXN], fa[MXN];
    int dis[MXN][20];
    namespace LCA {
        int dis[MXN], up[MXN][20], lg[MXN];
        void dfs(int u, int ba) {
            for(int i = head[u], v; ~i; i = cw[i].nex) {
                v = cw[i].v;
                if(v == ba) continue;
                dis[v] = dis[u] + 1, up[v][0] = u;
                dfs(v, u);
            }
        }
        void init() {
            for (int i = 2; i <= n; ++i) lg[i] = lg[i / 2] + 1;;
            dis[1] = 1;
            dfs(1, -1);
            for (int j = 1; j <= lg[n]; ++j)
                for (int i = 1; i <= n; ++i) up[i][j] = up[up[i][j - 1]][j - 1];
        }
        int lca(int x, int y) {
            if (dis[x] > dis[y]) swap(x, y);
            int k = dis[y] - dis[x];
            for (int i = 0; k; k = k / 2, ++i)
                if (k & 1) y = up[y][i];
            if (x == y) return x;
            k = dis[x];
            for (int i = lg[k]; i >= 0; --i)
                if (up[x][i] != up[y][i]) x = up[x][i], y = up[y][i];
            return up[x][0];
        }
        int query(int i, int j) {
            return dis[i] + dis[j] - 2 * dis[lca(i, j)];
        }
    }
    int get_dis(int i, int j) {
        if(i == j) return 0;
        if(dis[i][dep[i] - dep[j]]) return dis[i][dep[i] - dep[j]];
        dis[i][dep[i] - dep[j]] = LCA::query(i, j);
        return dis[i][dep[i] - dep[j]];
    }
    struct heap {
        static const int MAXE = N*60;
        int rt[MXN], tot;
        int sum[MAXE], ls[MAXE], rs[MAXE];
        void update(int p, int v, int l, int r, int&rt) {
            if(rt == 0) rt = ++ tot;
            if(l == r) {
                sum[rt] += v;
                return;
            }
            int mid = (l + r) >> 1;
            if(p <= mid) update(p, v, l, mid, ls[rt]);
            else update(p, v, mid + 1, r, rs[rt]);
            sum[rt] = sum[ls[rt]] + sum[rs[rt]];
        }
        int query(int L, int R, int l, int r, int rt) {
            if(L > R || rt == 0 || L > r || R < l) return 0;
            if(L <= l && r <= R) return sum[rt];
            int mid = (l + r) >> 1;
            if(L > mid) return query(L, R, mid + 1, r, rs[rt]);
            else if(R <= mid) return query(L,R,l,mid,ls[rt]);
            else {
                return query(L,mid,l,mid,ls[rt])+query(mid+1,R,mid+1,r,rs[rt]);
            }
        }
    } dison, disfa;
    inline void add_edge(int a, int b) {
        cw[++ tot].v = b, cw[tot].nex = head[a];
        head[a] = tot;
        cw[++ tot].v = a, cw[tot].nex = head[b];
        head[b] = tot;
    }
    int _tn;
    void dfs_pre(int u, int ba) {
        int mm = 0;
        siz[u] = 1;
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_pre(v, u);
            siz[u] += siz[v];
            mm = big(mm, siz[v]);
        }
        mm = big(mm, _tn - siz[u]);
        if(hvy == -1 || hvysiz > mm) {
            hvy = u;
            hvysiz = mm;
        }
    }
    void dfs_dis(int u, int ba, int d, int rt) {
        dison.update(d, ar[u], 0, n, dison.rt[rt]);
        siz[u] = 1;
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_dis(v, u, d + 1, rt);
            siz[u] += siz[v];
        }
    }
    void dfs_fa(int u, int ba, int d, int rt) {
        disfa.update(d, ar[u], 0, n, disfa.rt[rt]);
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(v == ba || vis[v]) continue;
            dfs_fa(v, u, d + 1, rt);
        }
    }
    void dfs_get(int u) {
    //    debug(u, _n, hvy)
        vis[u] = true;
        dfs_dis(u, -1, 0, u);
        for(int i = head[u], v; ~i; i = cw[i].nex) {
            v = cw[i].v;
            if(vis[v]) continue;
            hvy = hvysiz = -1;
    //        int tmp = siz[v];
            _tn = siz[v];
            dfs_pre(v, -1);
            dfs_fa(v, u, 1, hvy);
    //        debug(u, v, tmp, siz[v])
    //        assert(tmp == siz[v]);
            fa[hvy] = u;
            dep[hvy] = dep[u] + 1;
            dfs_get(hvy);
        }
    }
    int main() {
        n = read(), m = read();
        for(int i = 1; i <= n; ++i) ar[i] = read(), head[i] = -1;
        tot = -1;
        for(int i = 1, a, b; i < n; ++i) {
            a = read(), b = read();
            add_edge(a, b);
        }
        LCA::init();
        hvy = hvysiz = -1;
        _tn = n;
        dfs_pre(1, -1);
        dep[hvy] = 1;
        dfs_get(hvy);
    //    debug(m, get_dis(1, 3), dep[1], dep[3])
        int opt, x, y, lst, lastans = 0;
        while(m --) {
            opt = read(), x = read(), y = read();
            x ^= lastans, y ^= lastans;
            if(opt == 0) {
                lastans = dison.query(0, y, 0, n, dison.rt[x]);
                for(int i = x; fa[i]; i = fa[i]) {
    //                debug(i, fa[i])
                    lst = get_dis(x, fa[i]);
                    lastans += dison.query(0, y - lst, 0, n, dison.rt[fa[i]]) -
                            disfa.query(0, y - lst, 0, n, disfa.rt[i]);
                }
                printf("%d
    ", lastans);
            }else {
                dison.update(0, y - ar[x], 0, n, dison.rt[x]);
                for(int i = x; fa[i]; i = fa[i]) {
                    lst = get_dis(x, fa[i]);
                    dison.update(lst, y - ar[x], 0, n, dison.rt[fa[i]]);
                    disfa.update(lst, y - ar[x], 0, n, disfa.rt[i]);
                }
                ar[x] = y;
            }
        }
        return 0;
    }
    

    其他

    KD-Tree

    bzoj2648,bzoj2716

    概念参考:guoziqing506, 拳四郎, July_
    两种码风:devil-gary, RZZ

    const int INF = 0x3f3f3f3f;
    const int MXN = 5e5 + 7;
    const int MXE = 1e6 + 7;
    int n, m, Q;
    int ans;
    //动态开点
    const int K = 2;
    struct P {
        int x[K];
    }ap[MXN], pt;
    struct KDT {
        int x[K], Min[K], Max[K], split;
        int ls, rs;
    }kdt[MXE];
    int kdtNode, kdtRt;
    int cmp_k;
    bool cmp(const P&a, const P&b) {
        return a.x[cmp_k] < b.x[cmp_k];
    }
    void push_up(int rt) {
        int lc = kdt[rt].ls;
        if(lc) {
            for(int i = 0; i < K; ++i) {
                kdt[rt].Min[i] = sml(kdt[rt].Min[i], kdt[lc].Min[i]);
                kdt[rt].Max[i] = big(kdt[rt].Max[i], kdt[lc].Max[i]);
            }
        }
        lc = kdt[rt].rs;
        if(lc) {
            for(int i = 0; i < K; ++i) {
                kdt[rt].Min[i] = sml(kdt[rt].Min[i], kdt[lc].Min[i]);
                kdt[rt].Max[i] = big(kdt[rt].Max[i], kdt[lc].Max[i]);
            }
        }
    }
    void build(int l, int r, int &rt) {
        if(l > r) {
            rt = 0;
            return;
        }
        rt = ++ kdtNode;
        int d = 0;
        double mx = -1, ave, sum;
        for(int i = 0; i < K; ++i) {
            ave = sum = 0;
            for(int j = l; j <= r; ++j) ave += ap[j].x[i]; ave /= r-l+1;
            for(int j = l; j <= r; ++j) sum += o2(ap[j].x[i] - ave);
            if(sum > mx) mx = sum, d = i;
        }
        kdt[rt].split = cmp_k = d;
        int mid = (l + r) >> 1;
        nth_element(ap + l, ap + mid + 1, ap + r + 1, cmp);
        for(int i = 0; i < K; ++i) kdt[rt].x[i] = kdt[rt].Min[i] = kdt[rt].Max[i] = ap[mid].x[i];
        build(l, mid - 1, kdt[rt].ls), build(mid + 1, r, kdt[rt].rs);
        push_up(rt);
    }
    void insert(int &rt, int kd = 0) {
        if(!rt) {
            rt = ++ kdtNode;
            kdt[rt].split = (kd + 1) % K;
            for(int i = 0; i < K; ++i) kdt[rt].x[i] = kdt[rt].Min[i] = kdt[rt].Max[i] = pt.x[i];
            return;
        }
        for(int i = 0; i < K; ++i) {
            kdt[rt].Min[i] = sml(kdt[rt].Min[i], pt.x[i]);
            kdt[rt].Max[i] = big(kdt[rt].Max[i], pt.x[i]);
        }
        int d = kdt[rt].split;
        if(pt.x[d] < kdt[rt].x[d]) insert(kdt[rt].ls, d);
        else insert(kdt[rt].rs, d);
        push_up(rt);//?
    }
    inline int dist(int *x, int *y) {
        int ret = 0;
        for(int i = 0; i < K; ++i) ret += abs(x[i] - y[i]);
        return ret;
    }
    inline int dist(int *x, int *y, int *z) {//判断是否有交
        int ret = 0;
        for(int i = 0; i < K; ++i) {
            if(y[i] > x[i]) ret += y[i] - x[i];
            else if(x[i] > z[i]) ret += x[i] - z[i];
        }
        return ret;
    }
    void knnask(int rt) {
        if(!rt || dist(pt.x, kdt[rt].Min, kdt[rt].Max) >= ans) return;
        ans = sml(ans, dist(kdt[rt].x, pt.x));
        int d = kdt[rt].split;
        if(pt.x[d] < kdt[rt].x[d]) knnask(kdt[rt].ls), knnask(kdt[rt].rs);
        else knnask(kdt[rt].rs), knnask(kdt[rt].ls);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
    //    freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
    #endif
        n = read(), m = read();
        for(int i = 1; i <= n; ++i) {
            for(int j = 0; j < K; ++j) ap[i].x[j] = read();
        }
        kdtNode = kdtRt = 0;
        build(1, n, kdtRt);
        int opt, x, y;
        while(m --) {
            opt = read();
            for(int i = 0; i < K; ++i) pt.x[i] = read();
            if(opt == 1) insert(kdtRt);
            else {
                ans = INF;
                knnask(kdtRt);
                printf("%d
    ", ans);
            }
        }
        return 0;
    }
    

    虚树

    虚树就是把关键点从树立面拿出来,再补上他们的lca,形成新的树。
    讲解:here
    bzoj2286,bzoj3611,cf613D,bzoj3572

    namespace VT {
        struct lp {
            int v, nex;
            LL w;
        } cw[MXE];
        int tot, head[MXN], stak[MXN], top, d[MXN], is[MXN];
        void add_edge(int a, int b, LL c) {
            cw[++tot].v = b, cw[tot].nex = head[a], cw[tot].w = c;
            head[a] = tot;
            cw[++tot].v = a, cw[tot].nex = head[b], cw[tot].w = c;
            head[b] = tot;
        }
        bool cmp(const int &a, const int &b) {///tid is dfs number
            return LCA::tid[ar[a]] < LCA::tid[ar[b]];
        }
        void build(int n) {
            tot = head[1] = -1;
            stak[top = 1] = 1;
            for(int i = 1; i <= n; ++i) d[i] = i, is[ar[i]] = 1;
            sort(d + 1, d + 1 + n, cmp);
            for(int i = 1; i <= n; ++i) {
                if(ar[d[i]] == 1) continue;
                int lca = LCA::lca(ar[d[i]], stak[top]);
                if(lca != stak[top]) {
                    while(LCA::tid[lca] < LCA::tid[stak[top-1]]) {
                        add_edge(stak[top], stak[top-1], LCA::query(stak[top], stak[top-1]));
                        -- top;
                    }
                    if(lca == stak[top-1]) {
                        add_edge(stak[top], stak[top-1], LCA::query(stak[top], stak[top-1]));
                        -- top;
                    }else {
                        head[lca] = -1;
                        add_edge(lca, stak[top], LCA::query(lca, stak[top]));
                        stak[top] = lca;
                    }
                }
                stak[++top] = ar[d[i]];
                head[stak[top]] = -1;
            }
            for(int i = 2; i <= top; ++i) add_edge(stak[i], stak[i-1], LCA::query(stak[i], stak[i-1]));
        }
        LL dp[MXN];
        void dfs(int u, int ba) {
            dp[u] = 0;
            for(int i = head[u], v; ~i; i = cw[i].nex) {
                v = cw[i].v;
                if(v == ba) continue;
                dfs(v, u);
                if(is[v]) dp[u] += cw[i].w;
                else dp[u] += sml(dp[v], cw[i].w);
            }
        }
    }
    

    steiner斯坦纳树

    2019南昌邀请赛A题HDU4085
    这两题可以说几乎一样了,hdu4085只要求前k((kle 5))个点和后k个点两两之间一一对应,但并没有固定谁该和谁对应。
    邀请赛A题给定4对点,固定两两之间应该联通。写法差不多,改一下(check())状态的函数即可,合法状态要么不包含给定点对,要么给定点对的两个点都包含。
    注意有一个坑点是4对点中可能有重点。

    /*
    枚举状态sta时,遇到在第一类转移之后有更新的节点,将其加入队列,用spfa做一次迭代更新。普通的转
     移是不能保证最优性的,而spfa采用迭代逼近的方式,将更新过的点再进行更新,可以保证最后每个节点
     都是“最短路”。
    
    对于ZOJ WormHole Transportation 和 HDU Peach Blossom Spring,其解为一片斯坦纳生成
     森林,用dp[sta]数组来维护最优解,可利用f[i][sta]来松弛dp[sta],得到当前状态的最小代价。
     最后由小到大枚举状态,将森林在0代价的条件下合并成“生成树”即可。
     注意在这过程中要过滤掉非法状态。
     */
    const int MXN = 1e3 + 7;
    const int MXE = 1e4 + 7;
    int n, m, stnum;
    int head[MXN], tot;
    struct lp {
        int v, nex;
        int w;
    }cw[MXE];
    LL dp[(1<<10) + 5][35], val[MXN], f[(1<<10)+5];
    int in[MXN];
    queue<int> Q;
    string a, b, aa[4], bb[4];
    int X[4], Y[4], to[MXN], re[MXN];
    map<string, int> mp, mp2;
    void add_edge(int u, int v, int w) {
        cw[++tot].v = v, cw[tot].nex = head[u], cw[tot].w = w;
        head[u] = tot;
        cw[++tot].v = u, cw[tot].nex = head[v], cw[tot].w = w;
        head[v] = tot;
    }
    void spfa(int S) {
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            in[u] = 0;
            for(int i = head[u], v; ~i; i = cw[i].nex) {
                v = cw[i].v;
                if(dp[S][v] > dp[S][u] + cw[i].w) {
                    dp[S][v] = dp[S][u] + cw[i].w;
                    if(!in[v]) Q.push(v), in[v] = 1;
                }
            }
        }
    }
    void steiner() {
        clr(dp, 0x3f);
        for(int i = 0; i < stnum; ++i) {
            dp[1<<i][re[i]] = 0;
        }
        int sta = 1 << stnum;
        for (int S = 1; S < sta; ++S) {
            for (int x = S; x; x = (x-1)&S) {
                for(int i = 0; i < n; ++i) {
                    dp[S][i] = sml(dp[S][i], dp[x][i] + dp[S^x][i]);
                }
            }
            for(int i = 0; i < n; ++i) {
                in[i] = 0;
                if(dp[S][i] != INFLL && !in[i]) {
                    Q.push(i), in[i] = 1;
                }
            }
            spfa(S);
        }
    }
    bool check(int s) {
        bool flag = true;
        for(int i = 0; i < 4; ++i) {
            if(((s>>to[X[i]])&1) != ((s>>to[Y[i]])&1)) flag = false;
        }
        return flag;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
        //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
    #endif
        tot = -1;
        cin >> n >> m;
        for(int i = 0; i < n; ++i) {
            cin >> a;
            mp[a] = i;
            head[i] = -1;
        }
        for(int i = 1, x; i <= m; ++i) {
            cin >> a >> b >> x;
            add_edge(mp[a], mp[b], x);
        }
        for(int i = 0; i < 4; ++i) {
            cin >> aa[i] >> bb[i];
            X[i] = mp[aa[i]], Y[i] = mp[bb[i]];
            if(mp2[aa[i]] == 0) to[X[i]] = stnum ++, re[stnum - 1] = X[i];
            if(mp2[bb[i]] == 0) to[Y[i]] = stnum ++, re[stnum - 1] = Y[i];
            mp2[aa[i]] = mp2[bb[i]] = 1;
        }
        steiner();
        int sta = 1 << stnum;
        clr(f, 0x3f);
        for(int i = 1; i < sta; ++i) {
            for(int j = 0; j < n; ++j) f[i] = sml(f[i], dp[i][j]);
        }
    //    for(int i = 1; i < sta; ++ i) printf("%d ", f[i]); printf("
    ");
        for(int i = 1; i < sta; ++i) {
            if(check(i)) {
                for (int x = i; x; x = (x-1)&i) {
                    if(check(x)) f[i] = sml(f[i], f[x] + f[i ^ x]);
                }
            }
        }
        cout << f[sta - 1] << endl;
    #ifndef ONLINE_JUDGE
        cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
    #endif
        return 0;
    }
    

    zoj3613

    const int MXN = 1e3 + 7;
    const int MXE = 1e4 + 7;
    int n, m;
    int head[MXN], tot;
    struct lp {
        int v, nex;
        int w;
    }cw[MXE];
    int dp[(1<<10) + 5][35], val[MXN], f[(1<<10)+5];
    int in[MXN];
    queue<int> Q;
    int P[MXN], T[MXN], X[MXN], Y[MXN], pnum[MXN], re[MXN], t1, t2, stnum;
    void add_edge(int u, int v, int w) {
        cw[++tot].v = v, cw[tot].nex = head[u], cw[tot].w = w;
        head[u] = tot;
        cw[++tot].v = u, cw[tot].nex = head[v], cw[tot].w = w;
        head[v] = tot;
    }
    void spfa(int S) {
        while(!Q.empty()) {
            int u = Q.front(); Q.pop();
            in[u] = 0;
            for(int i = head[u], v; ~i; i = cw[i].nex) {
                v = cw[i].v;
                if(dp[S][v] > dp[S][u] + cw[i].w) {
                    dp[S][v] = dp[S][u] + cw[i].w;
                    if(!in[v]) Q.push(v), in[v] = 1;
                }
            }
        }
    }
    void steiner() {
        clr(dp, 0x3f);
        for(int i = 0; i < stnum; ++i) {
            dp[1<<i][re[i]] = 0;
        }
        int sta = 1 << stnum;
        for (int S = 1; S < sta; ++S) {
            for (int x = S; x; x = (x-1)&S) {
                for(int i = 0; i < n; ++i) {
                    dp[S][i] = sml(dp[S][i], dp[x][i] + dp[S^x][i]);
                }
            }
            for(int i = 0; i < n; ++i) {
                in[i] = 0;
                if(dp[S][i] != INFLL && !in[i]) {
                    Q.push(i), in[i] = 1;
                }
            }
            spfa(S);
        }
    }
    bool check(int s) {
        int cnt = 0;
        for(int i = 0; i < stnum; ++i) if(s&(1<<i)) cnt += pnum[i];
        return cnt >= 0;
    }
    int get(int s) {
        int cnt = 0, cnt2 = 0;
        for(int i = 0; i < stnum; ++i) {
            if(s&(1<<i)) {
                if (pnum[i] >= 0) cnt += pnum[i];
                else cnt2 -= pnum[i];
            }
        }
        if(cnt <= cnt2) return cnt;
        return 0;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
        //freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
    #endif
        tot = -1;
        n = read();
        for(int i = 0; i < n; ++i) {
            P[i] = read(), T[i] = read();
            if(P[i] && T[i]) -- P[i], -- T[i];
            if(P[i] || T[i]) {
                pnum[stnum] = P[i] - T[i];
                re[stnum] = i;
                ++ stnum;
            }
            head[i] = -1;
        }
        m = read();
        for(int i = 1, u, v, w; i <= m; ++i) {
            u = read(), v = read(), w = read();
            add_edge(u - 1, v - 1, w);
        }
        steiner();
        int sta = 1 << stnum;
        clr(f, 0x3f);
        for(int i = 1; i < sta; ++i) {
            for(int j = 0; j < n; ++j) f[i] = sml(f[i], dp[i][j]);
        }
    //    for(int i = 1; i < sta; ++ i) printf("%d ", f[i]); printf("
    ");
        for(int i = 1; i < sta; ++i) {
            if(check(i)) {
                for (int x = i; x; x = (x-1)&i) {
                    if(check(x) && check(i ^ x)) {
    //                    debug(i, x, i ^ x, f[i], f[x], f[i^x])
                        f[i] = sml(f[i], f[x] + f[i ^ x]);
                    }
                }
            }
        }
        int Maxnum = 0, Mincost = 0;
        for(int i = 1; i < sta; ++i) {
            if(f[i] != INF) {
                int num = get(i);
                if(num > Maxnum) {
                    Maxnum = num;
                    Mincost = f[i];
                }else if(num == Maxnum && f[i] < Mincost) {
                    Mincost = f[i];
                }
            }
        }
        printf("%d %d
    ", Maxnum, Mincost);
    #ifndef ONLINE_JUDGE
        cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
    #endif
        return 0;
    }
    

    DSU on Tree 2019南昌icpc K题

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define endl '
    '
    #define mk make_pair
    #define eb push_back
    #define SZ(x) ((int)(x).size())
    #define all(x) (x).begin(), (x).end()
    #define clr(a, b) memset((a),(b),sizeof((a)))
    #define iis std::ios::sync_with_stdio(false); cin.tie(0)
    #define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
    using namespace std;
    #pragma optimize("-O3")
    typedef long long LL;
    typedef unsigned long long uLL;
    typedef pair<int, int> pii;
    inline LL read() {
        LL x = 0;int f = 0;
        char ch = getchar();
        while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
        while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x = f ? -x : x;
    }
    inline void write(LL x, bool f) {
        if (x == 0) {putchar('0'); if(f)putchar('
    ');else putchar(' ');return;}
        if (x < 0) {putchar('-');x = -x;}
        static char s[23];
        int l = 0;
        while (x != 0)s[l++] = x % 10 + 48, x /= 10;
        while (l)putchar(s[--l]);
        if(f)putchar('
    ');else putchar(' ');
    }
    int lowbit(int x) { return x & (-x); }
    void debug_out() { cerr << '
    '; }
    template<typename T, typename ...R>void debug_out(const T &f, const R &...r) {cerr << f << " ";debug_out(r...);}
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
     
    const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
    const int mod = 998244353;
    const int MOD = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    const int MXN = 1e5 + 7;
    const int MXE = 2e5 + 7;
    
    int n, m;
    int dis[MXN], ar[MXN];
    std::vector<int> mp[MXN];
    map<pii, int> od[MXN];
    LL ans;
    map<pii, int>::iterator sit;
    void dfs(int u, int ba) {
        dis[u] = dis[ba] + 1;
        for(auto v: mp[u]) {
            dfs(v, u);
            if((int)od[v].size() > (int)od[u].size()) swap(od[u], od[v]);
            for(sit = od[v].begin(); sit != od[v].end(); ++ sit) {
                int D = (*sit).fi.fi, V = (*sit).fi.se;
                D = 2 * dis[u] - D + m;
                V = 2 * ar[u] - V;
                ans += od[u][mk(D, V)] * (*sit).se;
            }
            for(sit = od[v].begin(); sit != od[v].end(); ++ sit) od[u][(*sit).fi] += (*sit).se;
            od[v].clear();
        }
        od[u][mk(dis[u], ar[u])] += 1;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("E://ADpan//in.in", "r", stdin);
        // freopen("E://ADpan//out.out", "w", stdout);
    #endif
        n = read(), m = read();
        for(int i = 1; i <= n; ++i) ar[i] = read();
        for(int i = 2, x; i <= n; ++i) {
            x = read();
            mp[x].eb(i);
        }
        dfs(1, 0);
        printf("%lld
    ", ans * 2);
    #ifndef ONLINE_JUDGE
        cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
    #endif
        return 0;
    }
    
  • 相关阅读:
    SCILAB简介[z]
    UG OPEN API编程基础 2约定及编程初步
    Office 2003与Office 2010不能共存的解决方案
    UG OPEN API 编程基础 3用户界面接口
    NewtonRaphson method
    UG OPEN API编程基础 13MenuScript应用
    UG OPEN API编程基础 14API、UIStyler及MenuScript联合开发
    UG OPEN API编程基础 4部件文件的相关操作
    UG OPEN API编程基础 1概述
    16 UG Open的MFC应用
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/11297903.html
Copyright © 2011-2022 走看看