[Codeforces] 877E. Danil and a Part-time Job

題目連結:http://codeforces.com/problemset/problem/877/E
把樹壓扁後題目就轉化成有一個01序列,並且有兩種操作:查詢區間和跟把區間的bit反轉。稍微想一下會發現線段樹可以好好做他,所以就用線段樹維護一下就好了。
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
typedef pair<int,bool> PIB;
#define FF first
#define SS second
const int N = 200000 + 5;

class SegTree{
	private:
		PIB nodes[N<<2];
		int n;
		inline int lc(int x){return 2*x+1;}
		inline int rc(int x){return 2*x+2;}
		inline void push(int l, int r, int id){
			if(!nodes[id].SS) return;
			nodes[id].FF = r-l - nodes[id].FF;
			if(r-l > 1){
				nodes[lc(id)].SS ^= nodes[id].SS;
				nodes[rc(id)].SS ^= nodes[id].SS;
			}
			nodes[id].SS = 0;
		}
		inline void pull(int l, int r, int id){
			int val = 0, mid = (l+r)>>1;
			if(nodes[lc(id)].SS) val += mid-l-nodes[lc(id)].FF;
			else val += nodes[lc(id)].FF;
			if(nodes[rc(id)].SS) val += r-mid-nodes[rc(id)].FF;
			else val += nodes[rc(id)].FF;
			nodes[id].FF = val;
		}
		void build(int l, int r, int id, int arr[]){
			nodes[id].SS = 0;
			if(r-l == 1){
				nodes[id].FF = arr[l];
				return;
			}
			int mid = (l+r)>>1;
			build(l, mid, lc(id), arr);
			build(mid, r, rc(id), arr);
			nodes[id].FF = nodes[lc(id)].FF + nodes[rc(id)].FF;
		}
		int query(int ql, int qr, int l, int r, int id){
			if(qr <= l or r <= ql) return 0;
			push(l, r, id);
			if(ql <= l and r <= qr) return nodes[id].FF;
			int mid = (l+r)>>1;
			return query(ql, qr, l, mid, lc(id))+query(ql, qr, mid, r, rc(id));
		}
		void modify(int ql, int qr, int l, int r, int id){
			if(qr <= l or r <= ql) return;
			push(l, r, id);
			if(ql <= l and r <= qr){
				nodes[id].SS ^= 1;
				return;
			}
			int mid = (l+r)>>1;
			modify(ql, qr, l, mid, lc(id));
			modify(ql, qr, mid, r, rc(id));
			pull(l, r, id);
		}
	public:
		void build(int size_, int arr[]){
			n = size_;
			build(0, n, 0, arr);
		}
		int query(int l, int r){
			return query(l, r, 0, n, 0);
		}
		void modify(int l, int r){
			modify(l, r, 0, n, 0);
		}
} seg;

vector<int> G[N];
int val[N], arr[N], timer, time_in[N], time_out[N];
void dfs(int,int);

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n; cin>>n;
	for(int i=2;i<=n;i++){
		int x; cin>>x;
		G[x].PB(i);
	}
	for(int i=1;i<=n;i++) cin>>val[i];
	dfs(1, 1);
	seg.build(timer, arr);
	int q; cin>>q;
	while(q--){
		string opt; cin>>opt;
		if(opt=="get"){
			int u; cin>>u;
			cout<<seg.query(time_in[u], time_out[u])<<'\n';
		}else{
			int u; cin>>u;
			seg.modify(time_in[u], time_out[u]);
		}
	}
	return 0;
}

void dfs(int w, int f){
	time_in[w] = timer++;
	arr[time_in[w]] = val[w];
	for(auto i: G[w]) dfs(i, w);
	time_out[w] = timer;
}

留言

這個網誌中的熱門文章

[NPSC] 2009初賽 E. 檸檬汽水傳說

[TIOJ] 1902. 「殿仁.王,不認識,誰啊?」,然後他就死了……

[AtCoder] [經典競程 90 題] 024 - Select +/- One(★2)