suoi22 WRX知识树(dfs序)

把一条路径拆成到根的四个链(两端点、lca和fa[lca]),然后给dfs序中链的端点做单点修改、区间查询它的子树和再加上它原来的权值就可以了

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define lowb(x) ((x)&(-(x)))
#define REP(i,n0,n) for(i=n0;i<=n;i++)
#define PER(i,n0,n) for(i=n;i>=n0;i--)
#define MAX(a,b) ((a>b)?a:b)
#define MIN(a,b) ((a<b)?a:b)
#define CLR(a,x) memset(a,x,sizeof(a))
#define rei register int
using namespace std;
typedef long long ll;
const int maxn=1e6+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M;
int eg[maxn*][],egh[maxn],ect;
int v[maxn],fa[maxn],bfa[maxn];
int lq[maxn*][],lqh[maxn],lca[maxn][];
int dfn[maxn][],tot;
int stk[maxn][],sh;
ll tr[maxn];
int que[maxn];
bool vis[maxn]; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
} int getf(int x){return x==bfa[x]?x:bfa[x]=getf(bfa[x]);} inline void add(int x,ll y){
for(;x>&&x<=N;x+=lowb(x)) tr[x]+=y;
}
inline ll query(int x){
ll re=;for(;x>;x-=lowb(x)) re+=tr[x];return re;
} void dfs(){
stk[sh=][]=;stk[][]=egh[];
dfn[][]=tot=;
while(sh){
int x=stk[sh][],i=stk[sh][],b=eg[i][];
vis[x]=;
if(!i){
for(int j=lqh[x];j;j=lq[j][]){
int c=lq[j][];
if(vis[c]) lca[j>>][]=getf(c);
}
bfa[getf(x)]=fa[x];
dfn[x][]=tot;
sh--;continue;
}
stk[sh][]=eg[i][];
if(!vis[b]){
fa[b]=x;stk[++sh][]=b,stk[sh][]=egh[b];
dfn[b][]=++tot;
} }
} int main(){
//freopen(".in","r",stdin);
rei i;
N=rd(),M=rd();
for(i=;i<=N;i++) v[i]=rd();
for(i=;i<N;i++){
int a=rd(),b=rd();
adeg(a,b);adeg(b,a);
}for(i=;i<=N;i++) bfa[i]=i;
for(i=;i<=M;i++){
int a=rd(),b=rd();
if(!a){
que[i]=b;
}else{
int c=rd(),d=rd();
lca[i][]=d;
lq[i<<][]=b;lq[i<<][]=lqh[c];lqh[c]=i<<;
lq[i<<|][]=c;lq[i<<|][]=lqh[b];lqh[b]=i<<|;
}
}
dfs();
for(i=;i<=M;i++){
if(lca[i][]){
// printf("!%d %d %d\n",lca[i][0],lq[i<<1][0],lq[i<<1|1][0]);
add(dfn[lca[i][]][],-lca[i][]);
if(fa[lca[i][]]) add(dfn[fa[lca[i][]]][],-lca[i][]);
add(dfn[lq[i<<][]][],lca[i][]);
add(dfn[lq[i<<|][]][],lca[i][]);
// cout<<"mmm"<<endl;
}else{
printf("%lld\n",v[que[i]]+query(dfn[que[i]][])-query(dfn[que[i]][]-));
} }
return ;
}
上一篇:Android 自动编译、打包生成apk文件 3 - 使用SDK Ant方式


下一篇:C# 与Sql server 获取数据和执行命令