zoukankan      html  css  js  c++  java
  • 2018.12.15省选考试

    题目

    树上求子树内出现次数>=1且在区间【l,r】内的数

    题解

    这道题的最初版本是询问子树不同颜色个数, 是一道很经典的 “树比序列容易” 的题.
    在树上可以这样做: 对于每一种颜色, 将这种颜色的点提取出来按 DFS 序排序; 令每个点的贡
    献为 1, 相邻点的 LCA 的贡献为 −1, 于是问题转化为区间求和.
    修改颜色用这种做法是很好实现的, 只需对于每个颜色维护一个 set 即可.
    询问颜色区间也很简单, 把线段树换成主席树就可以了; 有修改的话, 换成树状数组套线段树就
    好了.
    时间复杂度 O(nlog 2 n).

    自己

    显然而又恶心而又绝望
    数据在博客文件里面

    代码

    // Copyright (C) 2017 __debug.
    
    // This program is free software; you can redistribute it and/or
    // modify it under the terms of the GNU General Public License as
    // published by the Free Software Foundation; version 3
    
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    
    // You should have received a copy of the GNU General Public License
    // along with this program; If not, see <http://www.gnu.org/licenses/>.
    
    
    #include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/priority_queue.hpp>
    
    #define x first
    #define y second
    #define MP std::make_pair
    #define SZ(x) ((int)(x).size())
    #define ALL(x) (x).begin(), (x).end()
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #ifdef __linux__
    #define getchar getchar_unlocked
    #define putchar putchar_unlocked
    #endif
    
    using std::pair;
    using std::vector;
    using std::string;
    
    typedef long long LL;
    typedef pair<int, int> Pii;
    
    const int oo = 0x3f3f3f3f;
    
    template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; }
    template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, true : false; }
    string procStatus()
    {
        std::ifstream t("/proc/self/status");
        return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
    }
    template<typename T> T read(T &x)
    {
        int f = 1;
        char ch = getchar();
        for (; !isdigit(ch); ch = getchar())
            f = (ch == '-' ? -1 : 1);
        for (x = 0; isdigit(ch); ch = getchar())
            x = 10 * x + ch - '0';
        return x *= f;
    }
    template<typename T> void write(T x)
    {
        if (x == 0) {
            putchar('0');
            return;
        }
        if (x < 0) {
            putchar('-');
            x = -x;
        }
        static char s[20];
        int top = 0;
        for (; x; x /= 10)
            s[++top] = x % 10 + '0';
        while (top)
            putchar(s[top--]);
    }
    // EOT
    
    const int MAXN = 1e5 + 5, LOGN = 18;
    
    int N, Q, online;
    vector<int> G[MAXN];
    int C[MAXN];
    
    void input()
    {
        read(N); read(Q); read(online);
        for (int i = 1; i <= N; ++i) {
            read(C[i]);
        }
        for (int i = 1; i < N; ++i) {
            int u, v;
            read(u); read(v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
    }
    
    std::set<int> S[MAXN];
    int dfsclock, dfnL[MAXN], dfnR[MAXN], id[MAXN];
    int dep[MAXN], fa[MAXN][LOGN];
    
    //set【颜色】 存下标 
    //处理括号序
    //求lca
    void dfs(int u, int f)
    {
        dfnL[u] = ++dfsclock;
        id[dfsclock] = u;
        S[C[u]].insert(dfnL[u]);
        for (auto v : G[u]) {
            if (v == f)
                continue;
            dep[v] = dep[u] + 1;
            fa[v][0] = u;
            for (int i = 1; i < LOGN; ++i) {
                fa[v][i] = fa[fa[v][i - 1]][i - 1];
            }
            dfs(v, u);
        }
        dfnR[u] = dfsclock;
    }
    
    int getLCA(int u, int v)
    {
        if (dep[u] < dep[v])
            std::swap(u, v);
        for (int i = LOGN - 1; i >= 0; --i) {
            if (dep[fa[u][i]] >= dep[v])
                u = fa[u][i];
        }
        if (u == v)
            return u;
        for (int i = LOGN - 1; i >= 0; --i) {
            if (fa[u][i] != fa[v][i]) {
                u = fa[u][i];
                v = fa[v][i];
            }
        }
        return fa[u][0];
    }
    
    namespace SEGT
    {
    
    const int SIZE = 8e7 + 5;
    
    int size, lc[SIZE], rc[SIZE];
    int sum[SIZE];
    
    inline int add(int v, int l, int r, int p, int x)
    {
        int u = ++size;
        if (l == r) {
            sum[u] = sum[v] + x;
            return u;
        }
        int mid = (l + r) >> 1;
        if (p <= mid) {
            lc[u] = add(lc[v], l, mid, p, x);
            rc[u] = rc[v];
        } else {
            lc[u] = lc[v];
            rc[u] = add(rc[v], mid + 1, r, p, x);
        }
        sum[u] = sum[lc[u]] + sum[rc[u]];
        return u;
    }
    
    inline int getsum(int u, int l, int r, int ql, int qr)
    {
        if (ql <= l && r <= qr)
            return sum[u];
        int mid = (l + r) >> 1;
        return (ql <= mid ? getsum(lc[u], l, mid, ql, qr) : 0) + (mid < qr ? getsum(rc[u], mid + 1, r, ql, qr) : 0);
    }
    void debug(int now,int l,int r) {
    	if(l==r) {
    		std::cout<<sum[now]<<" "<<l<<"
    ";
    		if(l==N) puts("____");
    		return ;
    	}
    	int mid=(l+r)>>1;
    	debug(lc[now],l,mid);
    	debug(rc[now],mid+1,r);
    }
    }
    namespace BIT
    {
    
    int root[MAXN];
    
    inline void add(int p, int q, int x)
    {
        for (; p <= N; p += p & -p) {
            root[p] = SEGT::add(root[p], 1, N, q, x),std::cout<<p<<" "<<q<<"<
    ";
        }
    }
    
    inline int getsum(int p, int ql, int qr)
    {
        int ret = 0;
        for (; p; p -= p & -p) {
    //    	SEGT::debug(root[p],1,N);
    		std::cout<<ql<<" "<<qr<<"!
    ";
            ret += SEGT::getsum(root[p], 1, N, ql, qr);
            std::cout<<ret<<">>>??
    ";
        }
        return ret;
    }
    }
    inline void contrib(int u, int v, int f)
    {
        u = id[u];
        v = id[v];
        BIT::add(C[u], dfnL[getLCA(u, v)], f);
    }
    
    void solve()
    {
        dep[1] = 1;
        dfs(1, 0);
    
        for (int i = 1; i <= N; ++i) {
            for (auto it = S[i].begin(); it != S[i].end(); ++it) {
                BIT::add(i, *it, +1);
         
    //            if (it != S[i].begin())
    //                contrib(*std::prev(it), *it, -1);//相邻两个之间减去他们的lca 
            }
        }
    //    for(int i=1;i<=N;++i) SEGT::debug(BIT::root[i],1,N);
    //    return;
        int lastans = 0;
        while (Q--) {
            int op, u, c, l, r;
            read(op); read(u);
            u ^= lastans;
            if (op == 1) {
                read(l); read(r);
                l ^= lastans;
                r ^= lastans;
    
                lastans = BIT::getsum(r, dfnL[u], dfnR[u]) ;//- BIT::getsum(l - 1, dfnL[u], dfnR[u]);
                write(lastans); putchar('
    ');
    
            } else if (op == 2) {
                read(c);
                c ^= lastans;
    
                auto it = S[C[u]].find(dfnL[u]);
                bool p = it != S[C[u]].begin();
                bool n = std::next(it) != S[C[u]].end();
                if (p)
                    contrib(*std::prev(it), *it, +1);
                if (n)
                    contrib(*it, *std::next(it), +1);
                if (p && n)
                    contrib(*std::prev(it), *std::next(it), -1);
    
                BIT::add(C[u], dfnL[u], -1);
                S[C[u]].erase(it);
                C[u] = c;
                BIT::add(C[u], dfnL[u], +1);
    
                it = S[C[u]].insert(dfnL[u]).x;
                p = it != S[C[u]].begin();
                n = std::next(it) != S[C[u]].end();
                if (p)
                    contrib(*std::prev(it), *it, -1);
                if (n)
                    contrib(*it, *std::next(it), -1);
                if (p && n)
                    contrib(*std::prev(it), *std::next(it), +1);
            }
            if (!online)
                lastans = 0;
        }
    }
    
    int main()
    {
    //	freopen("xmastree1.in","r",stdin);
    //	freopen("xmastree1.out","w",stdout);
        input();
        solve();
    }
    
    
  • 相关阅读:
    JSP 中文乱码显示处理解决方案
    jsp的9大对象
    获取各种路径
    输出自绘制图片
    Emmet基本使用方法
    <input type="file" />浏览时只显示指定文件类型
    使用dockerfile文件创建image
    gunicorn 访问日志配置与项目启动
    制作符合自己需求的镜像 docker image
    linux 查看系统信息
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10124248.html
Copyright © 2011-2022 走看看