利用待修改树上两点间gcd的想法,大概YY出了树剖的方法。
然后点开Disscuss,发现了immortalCO(%%%)的做法,发现把自己YY的细节都补充完了,感觉很兹瓷。
然而他说这是经典问题,对此我对自己狭窄的知识面的可怜的鏼题量感到有点内疚。
不过带修的独立集做法还是很兹瓷的!
AC代码如下:
#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define M 550005
using namespace std;
int n,tot,dfsclk,fst[N],pnt[N<<1],nxt[N<<1],sz[N],son[N],fa[N],pos[N],id[N],anc[N],ed[N];
ll ans,a[N],b[N],f[N],tx[M],ty[M];
ll read(){
ll x=0; char cr=getchar();
while (cr<'0' || cr>'9') cr=getchar();
while (cr>='0' && cr<='9'){ x=x*10+cr-'0'; cr=getchar(); }
return x;
}
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void dfs(int x){
int i,y; sz[x]=1;
for (i=fst[x]; i; i=nxt[i]){
y=pnt[i];
if (y!=fa[x]){
fa[y]=x;
dfs(y); sz[x]+=sz[y];
if (sz[y]>sz[son[x]]) son[x]=y;
a[x]+=f[y];
}
}
if (son[x]){
f[x]=min(a[x],b[x]); a[x]-=f[son[x]];
} else{
f[x]=b[x]; a[x]=1000000000000000000ll;
}
}
void dvd(int x,int tp){
int i,y; id[pos[x]=++dfsclk]=x; anc[x]=tp;
if (son[x]) dvd(son[x],tp); else ed[tp]=pos[x];
for (i=fst[x]; i; i=nxt[i]){
y=pnt[i];
if (y!=fa[x] && y!=son[x]) dvd(y,y);
}
}
void build(int k,int l,int r){
if (l==r){
tx[k]=a[id[l]]; ty[k]=b[id[l]]; return;
}
int mid=l+r>>1;
build(k<<1,l,mid); build(k<<1|1,mid+1,r);
tx[k]=tx[k<<1]+tx[k<<1|1]; ty[k]=min(ty[k<<1],ty[k<<1|1]+tx[k<<1]);
}
void mdy(int k,int l,int r,int x){
if (l==r){
tx[k]=a[id[x]]; ty[k]=b[id[x]]; return;
}
int mid=l+r>>1;
if (x<=mid) mdy(k<<1,l,mid,x); else mdy(k<<1|1,mid+1,r,x);
tx[k]=tx[k<<1]+tx[k<<1|1]; ty[k]=min(ty[k<<1],ty[k<<1|1]+tx[k<<1]);
}
void qry(int k,int l,int r,int x,int y){
if (x<=l && r<=y){
ans=min(ans+tx[k],ty[k]); return;
}
int mid=l+r>>1;
if (y>mid) qry(k<<1|1,mid+1,r,x,y); if (x<=mid) qry(k<<1,l,mid,x,y);
}
ll getans(int x){
ans=0; qry(1,1,n,pos[x],ed[anc[x]]); return ans;
}
int main(){
n=read();
int i,x,y;
for (i=1; i<=n; i++) b[i]=read();
for (i=1; i<n; i++){
x=read(); y=read();
add(x,y); add(y,x);
}
dfs(1); dvd(1,1); build(1,1,n);
int cas=read(); char cr;
while (cas--){
cr=getchar(); while (cr<'A' || cr>'Z') cr=getchar();
x=read();
if (cr=='C'){
b[x]+=read();
for (; x; x=y){
y=fa[anc[x]]; if (y) a[y]-=getans(anc[x]);
mdy(1,1,n,pos[x]); if (y) a[y]+=getans(anc[x]);
}
} else printf("%lld\n",getans(x));
}
return 0;
}
by lych
2016.12.4