CodeForces 877E DFS序+线段树
题意
就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身一共有几个灯是亮的。pow x,表示你需要改变x的子树和x本身上的灯的状态。
题解思路
这个题肯定是用DFS序了,为啥?因为树不好操作啊(我也不会啊),使用DFS序可以把树压成一维的一串数,这样就可以使用线段树来进行区间操作了。
话说这个题是我暑假限时训练中做的,看到这个题老开心了,但是让我万万没想到的是,这个题我交了11次才过,太心酸了。
代码实现
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<vector> using namespace std; const int maxn=2e5+100; struct node{ int l, r; int sum; int lazy; }t[maxn<<2]; vector<int> g[maxn]; int num[maxn]; int in[maxn], out[maxn], rk[maxn], cnt; int n, m; void dfs(int u, int fa) // { in[u]=++cnt;//这个是u进去的是时间 rk[cnt]=u; //不要忘了这个,这个是新生成的序列,也就是树被压成一维的那个数列。就是这忘了,害的我好苦。 int len=g[u].size(); for(int i=0; i<len; i++) { int v=g[u][i]; if(v==fa) continue; dfs(v, u); } out[u]=cnt; } void up(int rt) { t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; } void build(int rt, int l, int r) { t[rt].l=l; t[rt].r=r; t[rt].sum=0; t[rt].lazy=0; if(l==r) { t[rt].sum=num[rk[l]]; //这里也不要能错了,很重要。 return ; } int mid=(l+r)>>1; build(rt<<1, l, mid); build(rt<<1|1, mid+1, r); up(rt); } void down(int rt) { if(t[rt].lazy==0) return ; int ls=rt<<1, rs=rt<<1|1; t[ls].lazy=!t[ls].lazy; t[ls].sum=t[ls].r-t[ls].l+1-t[ls].sum; t[rs].lazy=!t[rs].lazy; t[rs].sum=t[rs].r-t[rs].l+1-t[rs].sum; t[rt].lazy=0; } void update(int rt, int l, int r) { if(l <= t[rt].l && t[rt].r <= r ) { t[rt].lazy = !t[rt].lazy; t[rt].sum=t[rt].r-t[rt].l+1-t[rt].sum; return ; } down(rt); int mid=(t[rt].l+t[rt].r)>>1; if(l<=mid) update(rt<<1, l, r); if(r>mid) update(rt<<1|1, l, r); up(rt); } int query(int rt, int l, int r) { if(l <= t[rt].l && t[rt].r <= r) { return t[rt].sum; } int ans=0; down(rt); int mid=(t[rt].l+t[rt].r)>>1; if(l<=mid) ans+=query(rt<<1, l, r); if(r>mid) ans+=query(rt<<1|1, l, r); return ans; } void init() { cnt=0; for(int i=0; i<=n; i++) { g[i].clear(); } } int main() { scanf("%d", &n); { cnt=0; int x; string op; if(n==1) { scanf("%d", &x); scanf("%d" , &m); while(m--) { int tmp; cin>>op; scanf("%d", &tmp); if(op=="get") printf("%d\n", x); else x=!x; } return 0; } for(int i=2; i<=n; i++) { scanf("%d", &x); g[x].push_back(i); g[i].push_back(x); } dfs(1, 0); for(int i=1; i<=n; i++) { scanf("%d", &num[i]); } build(1, 1, n); scanf("%d", &m); for(int i=1; i<=m; i++) { cin>>op; scanf("%d", &x); if(op=="get") { printf("%d\n", query(1, in[x], out[x])); } else { update(1, in[x], out[x]); } } } return 0; }