zoukankan      html  css  js  c++  java
  • bzoj3757 苹果树

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

    【RE提示】本题不支持提交了,具体可以见discuss,可以通过discuss的方法来做。

    【题解】

    树上莫队,就是把in/out的DFS序记录下来,每次查找要么查in[a]...in[b],要么查out[a]...in[b],加上LCA.

    然后就正常莫队啦!

    # include <math.h>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # 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 = 4e5 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, c[M];
    int head[M], nxt[M], to[M], tot = 0;
    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);
    }
    
    int fa[M][18], dep[M];
    int beg[M], end[M], DFN = 0, dfn[M];
    inline void dfs(int x, int fat=0) {
        beg[x] = ++DFN; dfn[DFN] = x;
        fa[x][0] = fat; dep[x] = dep[fat] + 1;
        for (int i=1; i<=17; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
        for (int i=head[x]; i; i=nxt[i]) 
            if(to[i] != fat) dfs(to[i], x);
        end[x] = ++DFN; dfn[DFN] = x;
    }
    
    inline int lca(int u, int v) {
        if(dep[u] < dep[v]) swap(u, v);
        for (int i=17; ~i; --i)
            if((dep[u]-dep[v]) & (1<<i)) u = fa[u][i];
        if(u == v) return u;
        for (int i=17; ~i; --i)
            if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
        return fa[u][0];
    }
    
    int bl[M], BLOCK;
    struct pa {
        int u, v, a, b, p, id;
        pa() {}
        pa(int u, int v, int a, int b, int p, int id) : u(u), v(v), a(a), b(b), p(p), id(id) {}
        friend bool operator < (pa a, pa b) {
            return bl[a.u] < bl[b.u] || (bl[a.u] == bl[b.u] && bl[a.v] < bl[b.v]);
        }
    }p[M];
    
    int ans[M];
    int t[M], s[M], cnt;
    inline void doit(int x) {
        t[x] ++;
        if(t[x] == 1) {
            ++s[c[x]];
            if(s[c[x]] == 1) ++cnt;
        } else {
            --s[c[x]];
            if(s[c[x]] == 0) --cnt;
        }
        if(t[x] == 2) t[x] = 0;
    }
    
    int main() {
        cin >> n >> m;
        for (int i=1; i<=n; ++i) scanf("%d", &c[i]);
        for (int i=1, u, v; i<=n; ++i) {
            scanf("%d%d", &u, &v);
            if(u && v) adde(u, v);
        }
        dfs(1);
        BLOCK = sqrt(n);
        for (int i=1; i<=DFN; ++i) bl[i] = (i-1)/BLOCK+1;
        for (int i=1, u, v, a, b; i<=m; ++i) {
            scanf("%d%d%d%d", &u, &v, &a, &b);
            int LCA = lca(u, v);
            if(beg[u] > beg[v]) swap(u, v);
            if(LCA == u) p[i] = pa(beg[u], beg[v], a, b, 0, i);
            else p[i] = pa(end[u], beg[v], a, b, LCA, i);
        }
        sort(p+1, p+m+1);
        int L = 1, R = 0;
        for (int i=1; i<=m; ++i) {
            while(R < p[i].v) ++R, doit(dfn[R]);
            while(R > p[i].v) doit(dfn[R]), --R;
            while(L > p[i].u) --L, doit(dfn[L]);
            while(L < p[i].u) doit(dfn[L]), ++L;
            if(p[i].p) doit(p[i].p);
            if(p[i].a == p[i].b) ans[p[i].id] = cnt;
            else {
                if(s[p[i].a] && s[p[i].b]) ans[p[i].id] = cnt-1;
                else ans[p[i].id] = cnt;
            }
            if(p[i].p) doit(p[i].p);
        }
        for (int i=1; i<=m; ++i) printf("%d
    ", ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    Rolling File Appender使用示例
    log4net生成dll文件
    看涨期权(call options)
    log4net file Appender使用示例
    log4net不能记录日志,IsErrorEnabled值为false
    C#委托
    打印事件处理顺序
    Zigbee、WiFi和433MHz无线技术
    log4net Tutorial
    安装服务出现异常
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3757.html
Copyright © 2011-2022 走看看