您的位置:首页 > 其它

bzoj 3052 [wc2013]糖果公园

2017-12-02 22:53 302 查看
传送门

Sol

置技能:莫队,树上莫队,待修改莫队,树上带修改莫队,足够厚的脸皮卡评测

至于树上集合的XOR等等这些操作可以看dalao的博客

链接

Code

// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;

const int N=100010;
int n,m,qnum;
int bin[20];
int SZ;
int c
;
struct node{
int to,nxt;
}e[N<<1];int head
,cnt;
LL v
,w
;
int bel
,tot;
struct ques{
int x,y,id,t;
bool operator < (const ques &b)const{
if(bel[x]==bel[b.x])
return bel[y]==bel[b.y]?t<b.t:(bel[y]<bel[b.y]);
else return bel[x]<bel[b.x];
}
}q
;int Q;
struct upd{
int x,y;
}ch
;int tim;
int fa
[20],siz
,dep
;
int st
,top;
int dfn
,xl;
LL num
;
bool vis
;
LL res;
LL ans
;

inline int read(){
int x=0,fx=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')fx=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*fx;
}

inline void add(int f,int t){
cnt++;
e[cnt]=(node){t,head[f]};
head[f]=cnt;
}

void dfs(int u){
st[++top]=u;
dfn[u]=++xl;
for(int j=1;j<=16;++j)
if(dep[u]>=bin[j]) fa[u][j]=fa[fa[u][j-1]][j-1];
else break;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u][0]) continue;
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs(v);
siz[u]+=siz[v];
if(siz[u]>=SZ){
siz[u]=0;
tot++;
while(st[top]!=u) bel[st[top--]]=tot;
}
}
siz[u]++;
}

int LCA(int x,int y){
if(dep[y]<dep[x]) swap(x,y);
int d=dep[y]-dep[x];
for(int i=0;bin[i]<=d;++i)
if(d&bin[i]) y=fa[y][i];
if(x==y) return x;
for(int i=log2(n);i>=0;--i)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}

inline void rever(int x){
int p=c[x];
LL &t=num[p];
if(vis[x]){
res-=w[t]*v[p];
t--;
}
else{
t++;
res+=w[t]*v[p];
}
vis[x]^=1;
}

void solve(int x,int y){
while(x!=y){
//cout<<x<<" "<<y<<endl;
if(dep[x]<dep[y]) swap(x,y);
rever(x);
x=fa[x][0];
}
}

void update(int pre){
int pos=ch[pre].x;
int &vp=c[pos];
int &vn=ch[pre].y;
if(vis[pos]){
rever(pos);
swap(vp,vn);
rever(pos);
}
else swap(vp,vn);
}

int main(){
bin[0]=1;
for(int i=1;i<=17;++i) bin[i]=bin[i-1]<<1;
memset(head,-1,sizeof(head));
scanf("%d%d%d",&n,&m,&qnum);
SZ=pow(n,2.0/3)*0.5;
for(int i=1;i<=m;++i) v[i]=read();
for(int i=1;i<=n;++i) w[i]=read();
int x,y;
for(int i=1;i<n;++i){
x=read();
y=read();
add(x,y);
add(y,x);
}
for(int i=1;i<=n;++i) c[i]=read();
dfs(1);
while(top) bel[st[top--]]=tot;
int op;
for(int i=1;i<=qnum;++i){
op=read();x=read();y=read();
if(op==0) ch[++tim]=(upd){x,y};
if(op==1){
if(dfn[x]>dfn[y]) swap(x,y);
q[++Q]=(ques){x,y,Q,tim};
}
}
sort(q+1,q+1+Q);
int now=0;
while(now<q[1].t) update(++now);
solve(q[1].x,q[1].y);
int lca=LCA(q[1].x,q[1].y);
rever(lca);
ans[q[1].id]=res;
rever(lca);
for(int i=2;i<=qnum;++i){
while(now<q[i].t) update(++now);
while(now>q[i].t) update(now--);
solve(q[i-1].x,q[i].x);
solve(q[i-1].y,q[i].y);
lca=LCA(q[i].x,q[i].y);
rever(lca);
ans[q[i].id]=res;
rever(lca);
}
for(int i=1;i<=Q;++i) printf("%lld\n",ans[i]);
return 0;
}

/*
4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: