1.设每个点的权值为 u − f a u u-fa_u u−fau,那么两个黑点的贡献就是他们到根的链并的权值和,可以通过链加求链和解决询问和单点修改。
2.对于子树修改,先对于这个奇数距离,开两个数据结构分别维护深度为奇数和深度为偶数的,那么就是子树翻转加上链加,可以再计算白点的链和来实现子树翻转标记。
3.注意需要求子树内黑点个数。
4.其实不是很长,只是询问修改操作很多而已。
A C C o d e \mathcal AC \ Code AC Code
#include<bits/stdc++.h>
#define maxn 200005
#define LL long long
using namespace std;
char cb[1<<16],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
void read(int &res){
char ch;
for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
int n,m;
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
void Node(int u,int v){
Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }
int col[maxn];
int pos[maxn],id[maxn],fa[maxn],son[maxn],sz[maxn],dep[maxn],tp[maxn],ed[maxn],tot;
int ssp[2][2][maxn];
void dfs0(int u,int ff){
sz[u] = 1 , fa[u] = ff , dep[u] = dep[ff] + 1;
ssp[dep[u]&1][col[u]][u] = 1;
for(int i=info[u],v;i;i=Prev[i]) if((v=to[i])^ff){
dfs0(v,u),sz[u]+=sz[v],(sz[v]>sz[son[u]])&&(son[u]=v);
for(int j=0;j<