• CF 966E May Holidays


    /*
    考虑对于询问分块, 每根号n个询问做一次
    考虑一次询问, 我们建立出虚树来每条链上的更改一定是一样的, 然后会有根号条链
    
    对于每条链上的点按照w基数排序并且合并相同, 然后每次更改 就是一个指针移动一格, 根号n次更改每次都要枚举一遍所有的链 所以是On的
    
    总体Nsqrt(N)
    
    比着 DOFYPXY 的代码打的
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define M 100010
    #define mmp make_pair
    using namespace std;
    int read() {
    	int nm = 0;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar());
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm;
    }
    int n, m, tote, dft, ans, t[M], q[M], r[M], deep[M], top[M], son[M], sz[M], u[M], st[M], id[M], key[M], dfn[M], fa[M];
    const int biao = 600;
    vector<int> to[M], buc[M << 1];
    bool b[M];
    
    void dfs(int now, int f) {
    	deep[now] = deep[f] + 1;
    	sz[now] = 1;
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		dfs(vj, now);
    		if(sz[son[now]] < sz[vj]) son[now] = vj;
    		sz[now] += sz[vj];
    	}
    }
    
    void dfs(int now) {
    	dfn[now] = ++dft;
    	if(son[now]) {
    		top[son[now]] = top[now];
    		dfs(son[now]);
    	}
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		if(vj == son[now]) continue;
    		top[vj] = vj;
    		dfs(vj);
    	}
    }
    
    int lca(int a, int b) {
    	while(top[a] != top[b]) {
    		if(deep[top[a]] < deep[top[b]]) swap(a, b);
    		a = fa[top[a]];
    	}
    	if(deep[a] > deep[b]) swap(a, b);
    	return a;
    }
    
    bool cmp(int a, int b) {
    	return dfn[a] < dfn[b];
    }
    
    int rec(int now) {
    	int a = b[now];
    	for(int i = 0; i < to[now].size(); i++) {
    		int vj = to[now][i];
    		a += rec(vj);
    	}
    	r[now] = t[now] - a;
    	return a;
    }
    #define pii pair<int, int>
    struct Note {
    	int hd, pnt, sum, dx;
    	vector<pii> s;
    	void clear() {
    		hd = pnt = sum = dx = 0;
    		vector<pii>().swap(s);
    	}
    } g[M];
    
    void work(int L, int R) {
    	rec(1);
    	for(int i = L; i <= R; i++) u[i - L] = q[i];
    	sort(u, u + R - L + 1, cmp);
    	int tp = 1, num = 1;
    	st[1] = key[1] = 1;
    	for(int i = 0; i <= R - L; i++) {
    		int A = lca(u[i], st[tp]);
    		while(deep[A] < deep[st[tp]]) {
    			if(deep[st[tp - 1]] <= deep[A]) {
    				g[st[tp--]].hd = A;
    				if(st[tp] != A) st[++tp] = A, key[++num] = A;
    				break;
    			}
    			g[st[tp]].hd = st[tp - 1];
    			tp--;
    		}
    		if(st[tp] != u[i]) st[++tp] = u[i], key[++num] = u[i];
    	}
    	for(; tp > 1; tp--) g[st[tp]].hd = st[tp - 1];
    	memset(id, 0, sizeof(id));
    
    	for(int i = 1; i <= num; i++) {
    		for(int p = fa[key[i]]; p != g[key[i]].hd; p = fa[p]) {
    			id[p] = key[i];
    		}
    	}
    	for(int i = 0; i <= (n << 1); i++) vector<int>().swap(buc[i]);
    
    	for(int i = 1; i <= n; i++) if(!b[i]) buc[r[i] + n].push_back(i);
    	for(int i = 0; i <= (n << 1); i++) {
    		for(int j = 0; j < buc[i].size(); j++) {
    			if(id[buc[i][j]]) {
    				int o = id[buc[i][j]], ss = g[o].s.size();
    				if(ss && g[o].s[ss - 1].first == i - n) g[o].s[ss - 1].second++;
    				else g[o].s.push_back(mmp(i - n, 1));
    			}
    		}
    	}
    	for(int i = 1; i <= num; i++)
    		for(int k = key[i]; g[k].pnt < g[k].s.size() && g[k].s[g[k].pnt].first < 0; g[k].pnt++);
    	for(int i = L; i <= R; i++) {
    		b[q[i]] ^= 1;
    		if(b[q[i]]) {
    			if(r[q[i]] < 0) ans--;
    			r[q[i]]--;
    			for(int p = q[i]; g[p].hd;) {
    				g[p].dx--;
    				if(g[p].pnt < g[p].s.size() && g[p].s[g[p].pnt].first + g[p].dx < 0) ans += g[p].s[g[p].pnt].second, g[p].pnt++;
    				p = g[p].hd, r[p]--;
    				if(b[p] == 0 && r[p] == -1) ans++;
    			}
    		} else {
    			r[q[i]]++;
    			if(r[q[i]] < 0) ans++;
    			for(int p = q[i]; g[p].hd;) {
    				g[p].dx++;
    				if(g[p].pnt && g[p].s[g[p].pnt - 1].first + g[p].dx >= 0) g[p].pnt--, ans -= g[p].s[g[p].pnt].second;
    				p = g[p].hd, r[p]++;
    				if(b[p] == 0 && r[p] == 0) ans--;
    			}
    		}
    		cout << ans << ' ';
    	}
    	for(int i = 1; i <= num; i++) g[key[i]].clear();
    }
    
    int main() {
    	n = read(), m = read();
    	for(int i = 2; i <= n; i++) fa[i] = read(), to[fa[i]].push_back(i);
    	dfs(1, 0);
    	top[1] = 1;
    	dfs(1);
    	for(int i = 1; i <= n; i++) t[i] = read();
    	for(int i = 1; i <= m; i++) q[i] = read();
    	for(int i = 1; i <= m; i += biao) work(i, min(i + biao - 1, m));
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    理解HashSet及使用
    Java 集合类详解
    Java-泛型编程-使用通配符? extends 和 ? super
    回调函数及其用法
    log4j.properties 详解与配置步骤
    约瑟夫环
    泛型的约束与局限性
    把代码字体加大的办法
    System.arraycopy方法
    泛型数组列表与反射
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10526649.html
Copyright © 2020-2023  润新知