树上莫队
题解详见VFK大爷的 :
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
orz vfleaking orz vfleaking orz vfleaking orz vfleaking
这题在本机对拍的时候,忘记在分块里面初始化1,导致所有节点都没有进行分块操作。结果自己拍大数据跑的贼快,大点都只要一秒不到???(可能是因为数据随机?原因成谜。。。)然后非常喜悦 地交上去就T光光了。
真是一段有趣的经历- -
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define reg register
#define N 100005
#define SIZE 2154
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1<<23, stdin), S == T) ? 0 : *S++)
using namespace std;
char B[1<<23], *S = B, *T = B;
bool vis[N];
ll ans, print[N], v[N];
int bin[20], col[N], w[N], last[N], que[N], belong[N], siz[N], block, fa[N][20], dep[N], tot[N];
struct edge{int next,to;}e[N<<1];int ecnt;
struct query{int x, y, t, id;}q[N];int qcnt;
struct change{int x, from, to;}c[N];int ccnt;
int in()
{
reg int r = 0;
reg char c = getc();
while(c<'0'||c>'9')c=getc();
while(c>='0'&&c<='9')r=r*10+c-'0',c=getc();
return r;
}
bool cmp(query a, query b)
{
if(belong[a.x]==belong[b.x] && belong[a.y]==belong[b.y])return a.t<b.t;
else if(belong[a.x]==belong[b.x])return belong[a.y]<belong[b.y];
else return belong[a.x]<belong[b.x];
}
void addedge(int a, int b)
{
e[++ecnt]=(edge){last[a],b};
last[a]=ecnt;
}
void addnode(int x, int f)
{
if(siz[belong[f]]<SIZE)
belong[x]=belong[f];
else
belong[x]=++block;
siz[belong[x]]++;
}
void makeblock()
{
que[0]=belong[1]=siz[1]=block=1;
for(int head=0, tail=1; head<tail; head++)
{
int x=que[head];
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(belong[y])continue;
que[tail++]=y;
addnode(y,x);
}
}
}
void dfs(int x)
{
dep[x]=dep[fa[x][0]]+1;
for(int i = 1; bin[i]<=dep[x]; i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(y==fa[x][0])continue;
fa[y][0]=x;
dfs(y);
}
}
void reverse(int x)
{
if(vis[x])ans-=w[tot[col[x]]]*v[col[x]], tot[col[x]]--;
else tot[col[x]]++, ans+=w[tot[col[x]]]*v[col[x]];
vis[x]=!vis[x];
}
void make(int x, int y)
{
while(x!=y)
{
if(dep[x]>dep[y])reverse(x), x=fa[x][0];
else reverse(y), y=fa[y][0];
}
}
void turn(int x, int y)
{
if(vis[x])
{
ans-=w[tot[col[x]]]*v[col[x]];
tot[col[x]]--;
tot[y]++;
ans+=w[tot[y]]*v[y];
}
col[x]=y;
}
int lca(int x, int y)
{
if(dep[x]<dep[y])swap(x,y);
int t = dep[x]-dep[y];
for(int i = 0; bin[i]<=t; i++)
if(t&bin[i])
x=fa[x][i];
for(int i = 19; i>=0; i--)
{
if(fa[x][i]!=fa[y][i])
x=fa[x][i], y=fa[y][i];
}
return x==y?x:fa[x][0];
}
int main()
{
int n=in(), m=in(), Q=in();
bin[0]=1;
for(int i = 1; i < 20; i++)
bin[i]=bin[i-1]<<1;
for(int i = 1; i <= m; i++)
v[i]=in();
for(int i = 1; i <= n; i++)
w[i]=in();
for(int i = 1, a, b; i < n; i++)
{
a=in(); b=in();
addedge(a,b);
addedge(b,a);
}
for(int i = 1; i <= n; i++)
col[i]=in();
makeblock();
dfs(1);
for(int i = 1; i <= Q; i++)
{
int op=in(), x=in(), y=in();
if(op==0)
{
c[++ccnt]=(change){x,col[x],y};
col[x]=y;
}
else
{
if(x>y)swap(x,y);
q[++qcnt]=(query){x,y,ccnt,qcnt};
}
}
sort(q+1,q+1+qcnt,cmp);
make(q[1].x,q[1].y);
for(;ccnt<q[1].t;ccnt++)
turn(c[ccnt+1].x, c[ccnt+1].to);
for(;ccnt>q[1].t;ccnt--)
turn(c[ccnt].x, c[ccnt].from);
int t=lca(q[1].x,q[1].y);
reverse(t);
print[q[1].id]=ans;
reverse(t);
for(int i = 2; i <= qcnt; i++)
{
for(;ccnt<q[i].t;ccnt++)
turn(c[ccnt+1].x, c[ccnt+1].to);
for(;ccnt>q[i].t;ccnt--)
turn(c[ccnt].x, c[ccnt].from);
make(q[i].x,q[i-1].x);
make(q[i].y,q[i-1].y);
int temp=lca(q[i].x,q[i].y);
reverse(temp);
print[q[i].id]=ans;
reverse(temp);
}
for(int i = 1; i <= qcnt; i++)
printf("%lld\n",print[i]);
}