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;
}
posted @ 2019-09-19 21:18  LORDXX  阅读(130)  评论(0编辑  收藏  举报