cf-877e Danil and a Part-time Job

题意

所有房间成一棵有根树,房间1为根节点,每一次pow操作要求把当前节点在内的,以及他的子树全部反转一遍即1变成0,0变成1。每一次get操作进行求和,算出该节点在内的和他子树所有房间为1的个数即求和。

方法:dfs序建线段树,用模板进行修改一下即可。区间反转问题还是一样,要对该区间操作为奇数才进行反转偶数次操作无效,也就对应了lazy标记该怎么推。先初始化线段树然后每一次如果是有效操作,那么sum变成(区间长度-sum)即翻转一次。针对一颗一般的树,我们如果要进行区间修改,一般都有dfs序进行转化成线段树,即求出每一个节点他的子树的开始编号和结束编号,这样因为每一次我们深度优先就可以保证更新区间是连续的。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<map>
//#include<regex>
#include<cstdio>
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
int read()
{
    char ch = getchar(); int x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int n,q;
int st[N], ed[N];
int sum[N << 2], lazy[N << 2];
struct  {
    int to, next;
}edge[N];
int head[N];
int cnt = 0;
int num = 0;
void addedge(int fr, int to)
{
    edge[cnt].to = to;
    edge[cnt].next = head[fr];
    head[fr] = cnt++;
}
void dfs(int u)
{
    st[u] = ++num;
    for (int i = head[u]; ~i; i = edge[i].next)
    {
        dfs(edge[i].to);
    }
    ed[u] = num;
}
void pushup(int root)
{
    sum[root] = sum[lrt] + sum[rrt];
}
void pushdown(int root, int l, int r)
{
    int len = (r - l + 1);
    int lenl = len - (len >> 1); int lenr = (len) >> 1;
    if (lazy[root] % 2)
    {
        lazy[lrt] += lazy[root];
        lazy[rrt] += lazy[root];
        sum[lrt] = lenl - sum[lrt];
        sum[rrt] = lenr - sum[rrt];
        lazy[root] = 0;
    }
}
void build(int l, int r, int root)
{
    lazy[root] = 0;
    if (l == r) { sum[root] = 0; return; }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(root);
}
void init(int l, int r, int root, int pos, int val)
{
    if (l == r) { sum[root] = val; return; }
    int mid = (l + r) >> 1;
    if (pos <= mid)init(lson, pos, val);
    else init(rson, pos, val);
    pushup(root);
}
void update(int l, int r, int root, int lf, int rt)
{
    if (lf <= l && r <= rt)
    {
        sum[root] = (r - l + 1) - sum[root];
        lazy[root]++;
        return;
    }
    pushdown(root, l, r);
    int mid = (l + r) >> 1;
    if (lf <= mid)update(lson, lf, rt);
    if (rt > mid)update(rson, lf, rt);
    pushup(root);
}
int querry(int l, int r, int root, int lf, int rt)
{
    if (lf <= l && r <= rt)return sum[root];
    pushdown(root, l, r);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (lf <= mid)ans += querry(lson, lf, rt);
    if (rt > mid)ans += querry(rson, lf, rt);
    return ans;
}
int main()
{
    memset(head, -1, sizeof(head));
    n = read(); int x;
    upd(i,2, n)
    {
        x = read(); addedge(x, i);
    }
    build(1, n, 1);
    dfs(1);
    up(i, 0, n)
    {
        x = read();
        init(1, n, 1, st[i + 1], x);
    }
    q = read();
    char s[20];
    while (q--)
    {
        scanf("%s", s);
        if (s[0] == 'g')
        {
            x = read();
            cout << querry(1, n, 1, st[x], ed[x]) << endl;
        }
        else
        {
            x = read();
            update(1, n, 1, st[x], ed[x]);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LORDXX/p/11552663.html
job