zoukankan      html  css  js  c++  java
  • Codeforces Round #442 (Div. 2) 877E

    Codeforces Round #442 (Div. 2) 877E - Danil and a Part-time Job 

    emmmm第一次见的东西感觉都好神奇

    这里dfs序可以通过对树的遍历对各个节点进行区间分配,那么在接下来的线段树中,可以转变为对每个节点所对应的子树进行访问

    一开始感觉有些混乱,emmmm,理解上有困难的话……emmm,其实线段树维护的是区间,

    而dfs序只是根据题意对节点(线段树的叶子?不要去管它的父亲或者线段树数组内部的结构)管辖区间的建立,因为题目中要求访问以*为根的子树的情况,在用到线段树时,

    需要提供区间的左右端点,也就是dfs序所建立的L[*],R[*],只需要将主函数中访问线段树时的区间[L,R]换为【L[*],R[*]】就可以了……

    emmmm好像说了一堆废话orz

    #include<iostream>
    #include<stdio.h>
    #include<string>
    #include<vector>
    using namespace std;
    const int N = 2e5 + 5;
    vector<int>g[N];
    int L[N], R[N];
    int cnt=0, n, T;
    struct tree {
        int l, r, add, c[2];
    }t[N << 2];
    void init()
    {
        for (int i = 0; i < N; i++)
            g[i].clear();
        cnt = 0;
    }
    void dfs(int u, int fa)
    {
        L[u] = ++cnt;
        for (auto v : g[u])
        {
            if (v != fa)
                dfs(v, u);
        }
        R[u] = cnt;
    }
    void push_up(int rt)
    {
        for (int i = 0; i < 2; i++)
            t[rt].c[i] = t[rt << 1].c[i] + t[rt << 1 | 1].c[i];
    }
    void push_down(int rt)
    {
        if (t[rt].add)
        {
            swap(t[rt << 1].c[0], t[rt << 1].c[1]);
            swap(t[rt << 1 | 1].c[0], t[rt << 1 | 1].c[1]);
            t[rt << 1].add ^= 1;
            t[rt << 1 | 1].add ^= 1;
            t[rt].add = 0;
        }
    }
    void build(int l, int r, int rt)
    {
        t[rt].l = l; t[rt].r = r;
        t[rt].add = 0;
        if (l == r)
        {
            t[rt].c[0] = 1;
            t[rt].c[1] = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, rt << 1);
        build(mid + 1, r, rt << 1 | 1);
        push_up(rt);
    }
    void update(int l, int r, int rt)
    {
        if (t[rt].l == l&&t[rt].r == r)
        {
            t[rt].add ^= 1;
            swap(t[rt].c[0], t[rt].c[1]);
            return;
        }
        int mid = (t[rt].l + t[rt].r) >> 1;
        push_down(rt);
        if (r <= mid)
            update(l, r, rt << 1);
        else if (l > mid)
            update(l, r, rt << 1 | 1);
        else
            update(l, mid, rt << 1),update(mid+1, r, rt << 1 | 1);
        push_up(rt);
    }
    int query(int l, int r, int rt)
    {
        if (t[rt].r == r&&t[rt].l == l)
            return t[rt].c[1];
        int mid = (t[rt].l + t[rt].r) >> 1;
        push_down(rt);
        if (r <= mid)
            return query(l, r, rt << 1);
        else if (l > mid)
            return query(l, r, rt << 1 | 1);
        else
            return query(l, mid, rt << 1) + query(mid+1,r, rt << 1 | 1);
    }
    int main()
    {
        init();
        cin >> n;
        for (int i = 2; i <= n; i++)
        {
            cin >> T;
            g[T].push_back(i);
        }
        dfs(1, 1);
        build(1, cnt, 1);
        for (int i = 1; i <= n; i++)
        {
            int m;
            cin >> m;
            if (m)
                update(L[i], L[i], 1);
        }
        cin >> T;
        string s;
        for (int i = 0; i < T; i++)
        {
            int m;
            cin >> s >> m;
            if (s[0] == 'g')
                cout << query(L[m], R[m], 1) << endl;
            else update(L[m], R[m], 1);
        }
        return 0;
    }
  • 相关阅读:
    js点击按钮触发事件的方法(含函数的写法)
    操作文件
    克隆别人的仓库,提交到自己的远程仓库的方法
    时间戳变成 标准时间展示的方法
    还没看的书
    print 和 println的区别
    初学java记录
    java 的一个hellow word 代码解释
    eclipse 创建一个java项目 运行
    Eclipse环境配置
  • 原文地址:https://www.cnblogs.com/Egoist-/p/7747842.html
Copyright © 2011-2022 走看看