zoukankan      html  css  js  c++  java
  • bzoj3648 寝室管理

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3648

    【题解】

    明天就要去ctsc/apio了有点小激动啊(题解无关

    这道题如果是树就是一个裸的点分治+BIT啦!

    环套树啊。。去掉环上一条边,点分+BIT算一下。

    然后考虑通过这条边,一定是某点环套树-》边-》某点环套树

    一遍扫环BIT计算即可。

    这样例神坑啊。。少了个2

    真正的样例可以看程序最后(答案没错)

    # include <stdio.h>
    # include <string.h>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 2e5 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, K;
    int head[M], nxt[M], to[M], tot=1; bool del[M];
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    inline void adde(int u, int v) {
        add(u, v), add(v, u);
    }
    
    ll ans = 0;
    
    // ================== BIT =================== //
    namespace BIT {
        const int M = 6e5 + 10;
        int c[M], n;
        # define lb(x) (x&(-x))
        inline void init(int _n) {
            n = _n;
            memset(c, 0, sizeof c);
        }
        inline void edt(int x, int d) {
            for (; x<=n; x+=lb(x)) c[x] += d;
        }
        inline int sum(int x) {
            int ret = 0;
            for (; x; x-=lb(x)) ret += c[x];
            return ret;
        }
        inline int sum(int x, int y) {
            return sum(y) - sum(x-1);
        }
        # undef lb
    }
    
    // ================== dfz =================== //
    int sz[M], mx[M];
    bool vis[M];
    inline void getsz(int x, int fa=0) {
        sz[x] = 1, mx[x] = 0;
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || to[i] == fa || vis[to[i]]) continue;
            getsz(to[i], x);
            sz[x] += sz[to[i]];
            if(sz[to[i]] > mx[x]) mx[x] = sz[to[i]];
        }
    }
    
    int mi, centre;
    inline void getcentre(int x, int tp, int fa=0) {
        if(sz[tp] - sz[x] > mx[x]) mx[x] = sz[tp] - sz[x];
        if(mx[x] < mi) mi = mx[x], centre = x;
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || to[i] == fa || vis[to[i]]) continue;
            getcentre(to[i], tp, x);
        }
    }
    
    inline void getans(int x, int d, int fa=0) {
        ans += BIT::sum(max(1, K-d-1), n);
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || to[i] == fa || vis[to[i]]) continue;
            getans(to[i], d+1, x);
        }
    }
    
    inline void addans(int x, int d, int fa=0) {
        BIT::edt(d, 1);
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || to[i] == fa || vis[to[i]]) continue;
            addans(to[i], d+1, x);
        }
    }
        
    inline void delans(int x, int d, int fa=0) {
        BIT::edt(d, -1);
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || to[i] == fa || vis[to[i]]) continue;
            delans(to[i], d+1, x);
        }
    }
    
    
    inline void dfz(int x) {
        getsz(x); mi = n;
        getcentre(x, x);
        x = centre;
        // do something
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || vis[to[i]]) continue;
            getans(to[i], 1, x);
            addans(to[i], 1, x);
        }
        ans += BIT::sum(K-1, n);
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || vis[to[i]]) continue;
            delans(to[i], 1, x);
        }
        vis[x] = 1;
        for (int i=head[x]; i; i=nxt[i]) {
            if(del[i] || vis[to[i]]) continue;
            dfz(to[i]);
        }
    } 
    
    inline void solve_dfz() {
        memset(vis, 0, sizeof vis);
        BIT::init(n); dfz(1);
    }
    
    int st[M], stn, c[M], cn;
    inline void dfs_circle(int x, int fa=0) {
        if(cn) return;
        if(vis[x]) {
            for (int i=stn; st[i]!=x; --i) c[++cn] = st[i];
            c[++cn] = x;
            return ;
        }
        st[++stn] = x;
        vis[x] = 1; 
        for (int i=head[x]; i; i=nxt[i]) {
            if(to[i] == fa) continue;
            dfs_circle(to[i], x);
        }
        --stn;
    }
    
    int d[M], dn=0;
    inline void getdis(int x, int dis, int fa=0) {
        d[++dn] = dis;
        for (int i=head[x]; i; i=nxt[i]) {
            if(to[i] == fa || del[i] || vis[to[i]]) continue;
            getdis(to[i], dis+1, x);
        }
    }
    
    inline void solve() {
        stn = cn = 0;
        dfs_circle(1);
    //    printf("%d
    ", cn);
    //    for (int i=1; i<=cn; ++i) printf("%d ", c[i]);
    //    puts("");
        for (int i=head[c[1]]; i; i=nxt[i]) {
            if(to[i] == c[cn]) {
                del[i] = 1; del[i^1] = 1;
                break;
            }
        }
        solve_dfz();
        // cross c[cn]->c[1]
    //    printf("%lld
    ", ans);
        BIT::init(n);
        memset(vis, 0, sizeof vis);
        for (int i=1; i<=cn; ++i) vis[c[i]] = 1;
        for (int i=1; i<=cn; ++i) {
            dn = 0;
            getdis(c[i], 0);
            for (int j=1; j<=dn; ++j) ans += BIT::sum(max(1, K-(cn-i+1)-d[j]), n);
            for (int j=1; j<=dn; ++j) BIT::edt(d[j]+i, 1);
        }
        printf("%lld
    ", ans);
    }
    
    int main() {
        scanf("%d%d%d", &n, &m, &K);
        for (int i=1, u, v; i<=m; ++i) {
            scanf("%d%d", &u, &v);
            adde(u, v);
        }
        if(n == m) solve();
        else solve_dfz(), printf("%lld
    ", ans);
        return 0;
    }
    /*
    5 5 2
    1 3
    2 4
    3 5
    4 1
    5 2
    */
    View Code
  • 相关阅读:
    elementui问题汇总
    微信小程序实现微信授权登录
    微信小程序数据存储
    小程序使用第三方服务,需要中转到一个h5页面,返回到指定页面
    小程序开发,通过左上角返回到指定页面
    万恶之源-基本数据类型(list,tuple)
    基础中的基础
    mybatis_plus实现自动填充和逻辑删除
    本地端口占用解决方案
    maven定义版本以来报红解决方案
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3648.html
Copyright © 2011-2022 走看看