• 存一些东西


    @

    头文件

    #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;
    }
    
  • 相关阅读:
    安卓组件service
    安卓组件-BroadcastReceiver
    【bug】java.lang.NoSuchMethodError: android.widget.TextView.setBackground
    【转】安卓毛玻璃效果
    INSTALL_FAILED_UPDATE_INCOMPATIBLE
    安卓 异步线程更新Ui
    OC语言-03-OC语言-三大特性
    OC语言-02-OC语言-基础知识
    OC语言-01-面向过程与面向对象思想
    C语言-07-预处理、typedef、static和extern
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/11297903.html
Copyright © 2020-2023  润新知