题解:
NOIP之前当然要做做NOIp题啦!
这道题并不难(想),把一个点的权值定为 乘上子树黑点个数,然后就相当于是支持查询链和,链修改,子树修改了,用了链剖分开维护奇偶的情况即可。
时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(LL x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+'0');
}
const int N=2e5+50;
int n,m,col[N],pos[N];
int tot_sze[N],sze[N][2][2],son[N],top[N],fa[N],dep[N],in[N],out[N],ind;
vector <int> g[N];
struct PT {
int sum[N<<2],cnt[N<<2],rev[N<<2];
inline void build(int k,int l,int r,int flag) {
if(l==r) {
sum[k]=(dep[pos[l]]&1)==flag;
cnt[k]=(sum[k] && col[pos[l]]==1);
return;
} int mid=(l+r)>>1;
build(k<<1,l,mid,flag);
build(k<<1|1,mid+1,r,flag);
sum[k]=sum[k<<1]+sum[k<<1|1];
cnt[k]=cnt[k<<1]+cnt[k<<1|1];
}
inline void upt(int k) {
cnt[k]=cnt[k<<1]+cnt[k<<1|1];
}
inline void opt(int k) {
rev[k]^=1;
cnt[k]=sum[k]-cnt[k];
}
inline void pushdown(int k) {
if(rev[k]) {
opt(k<<1); opt(k<<1|1);
rev[k]=0;
}
}
inline int ask(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) return cnt[k];
pushdown(k); int mid=(l+r)>>1;
if(R<=mid) return ask(k<<1,l,mid,L,R);
else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
else return ask(k<<1,l,mid,L,R)+ask(k<<1|1,mid+1,r,L,R);
}
inline void opt(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) {opt(k); return;}
pushdown(k); int mid=(l+r)>>1;
if(R<=mid) opt(k<<1,l,mid,L,R);
else if(L>mid) opt(k<<1|1,mid+1,r,L,R);
else opt(k<<1,l,mid,L,R), opt(k<<1|1,mid+1,r,L,R);
upt(k);
}
inline int opt(int l,int r) {
int ans=ask(1,1,n,l,r);
opt(1,1,n,l,r);
return ans;
}
inline void init(int flag) {
build(1,1,n,flag);
}
} pt[2];
struct ST {
LL sum[N<<2][2],val[N<<2],rev[N<<2],tag[N<<2];
inline void upt(int k) {
sum[k][0]=sum[k<<1][0]+sum[k<<1|1][0];
sum[k][1]=sum[k<<1][1]+sum[k<<1|1][1];
}
inline void add(int k,int v) {
tag[k]+=v;
sum[k][0]-=v*val[k];
sum[k][1]+=v*val[k];
}
inline void opt(int k) {
tag[k]=-tag[k];
swap(sum[k][0],sum[k][1]);
rev[k]^=1;
}
inline void pushdown(int k) {
if(rev[k]) opt(k<<1), opt(k<<1|1), rev[k]=0;
if(tag[k]) add(k<<1,tag[k]), add(k<<1|1,tag[k]), tag[k]=0;
}
inline void build(int k,int l,int r,int flag) {
if(l==r) {
val[k]=pos[l]-fa[pos[l]];
sum[k][0]=val[k]*sze[pos[l]][flag][0];
sum[k][1]=val[k]*sze[pos[l]][flag][1];
return;
} int mid=(l+r)>>1;
build(k<<1,l,mid,flag);
build(k<<1|1,mid+1,r,flag);
val[k]=val[k<<1]+val[k<<1|1];
upt(k);
}
inline void inc(int k,int l,int r,int L,int R,int v) {
if(L<=l && r<=R) {add(k,v); return;}
pushdown(k); int mid=(l+r)>>1;
if(R<=mid) inc(k<<1,l,mid,L,R,v);
else if(L>mid) inc(k<<1|1,mid+1,r,L,R,v);
else inc(k<<1,l,mid,L,R,v), inc(k<<1|1,mid+1,r,L,R,v);
upt(k);
}
inline void opt(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) {opt(k); return;}
pushdown(k); int mid=(l+r)>>1;
if(R<=mid) opt(k<<1,l,mid,L,R);
else if(L>mid) opt(k<<1|1,mid+1,r,L,R);
else opt(k<<1,l,mid,L,R), opt(k<<1|1,mid+1,r,L,R);
upt(k);
}
inline LL ask(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) {return sum[k][1];}
pushdown(k); int mid=(l+r)>>1;
if(R<=mid) return ask(k<<1,l,mid,L,R);
else if(L>mid) return ask(k<<1|1,mid+1,r,L,R);
else return ask(k<<1,l,mid,L,R)+ask(k<<1|1,mid+1,r,L,R);
}
inline void add(int l,int r,int v) {
inc(1,1,n,l,r,v);
}
inline void opt(int l,int r) {
opt(1,1,n,l,r);
}
inline LL ask(int l,int r) {
return ask(1,1,n,l,r);
}
inline void init(int flag) {
build(1,1,n,flag);
}
} st[2];
inline void dfs(int x,int f) {
dep[x]=dep[f]+1; fa[x]=f;
tot_sze[x]=sze[x][dep[x]&1][col[x]==1]=1;
for(auto v:g[x]) if(v^f) {
dfs(v,x);
sze[x][0][0]+=sze[v][0][0];
sze[x][0][1]+=sze[v][0][1];
sze[x][1][0]+=sze[v][1][0];
sze[x][1][1]+=sze[v][1][1];
tot_sze[x]+=tot_sze[v];
if(tot_sze[son[x]]<tot_sze[v]) son[x]=v;
}
}
inline void Dfs(int x,int f) {
top[x]=f; in[x]=++ind; pos[ind]=x;
if(son[x]) Dfs(son[x],f);
for(auto v:g[x])
if(v^fa[x] && v^son[x]) Dfs(v,v);
out[x]=ind;
}
int main() {
n=rd(), m=rd();
for(int i=1;i<=n;i++) col[i]=rd();
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
g[x].push_back(y);
g[y].push_back(x);
} dfs(1,0); Dfs(1,1);
pt[0].init(0);
pt[1].init(1);
st[0].init(0);
st[1].init(1);
for(int i=1;i<=m;i++) {
int op=rd(), x=rd(), c=dep[x]&1;
if(op==1) {
int tot=sze[x][c^1][0]+sze[x][c^1][1];
int cnt=pt[c^1].opt(in[x],out[x]);
for(int u=fa[x];u;u=fa[top[u]]) {
st[c^1].add(in[top[u]],in[u],-cnt);
st[c^1].add(in[top[u]],in[u],tot-cnt);
} st[c^1].opt(in[x],out[x]);
} else if(op==2) {
int cnt=pt[c].opt(in[x],in[x]);
for(int u=x;u;u=fa[top[u]])
st[c].add(in[top[u]],in[u],cnt?-1:1);
} else {
LL ans=0;
for(int u=x;u;u=fa[top[u]])
ans+=st[0].ask(in[top[u]],in[u])+st[1].ask(in[top[u]],in[u]);
W(ans), putchar('\n');
}
}
}