Description
Input
Output
Sample Input
Sample Input
Sample Output
84
131
27
84
131
27
84
HINT
bzoj上总时限是250S。考试时单点10S
这题可以用莫队来做。先求出dfs序。然后把树上询问改成在dfs序上的区间询问。然后就和队列的莫队一样了。
以左端点,右端点,时间分别为第一、第二、第三关键字排序
至于分块大小我觉得不是太离谱就行吧。。看网上都是n^(2/3)的。可我自己写的n^(1/2)的更快
交了几次勉强卡进了100S
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int next;
}a[200001];
int head[100001];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
struct que
{
int u,v,t;
int p;
long long x;
}ask[100001];
struct rechange
{
int x,s,t;
}c[100001];
//--------------------------LCA
int deep[100001];
int fa[100001];
bool v[100001];
int ans[100001][22];
long long val[100001],w[100001];
inline void bfs(int r)
{
int i,j;
deep[r]=1;
for(i=0;i<=21;i++)
ans[r][i]=r;
queue <int>Q;
while(!Q.empty())
Q.pop();
Q.push(r);
v[r]=true;
while(!Q.empty())
{
int d=Q.front();
Q.pop();
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(!v[t])
{
v[t]=true;
Q.push(t);
fa[t]=d;
deep[t]=deep[d]+1;
ans[t][0]=d;
int dt;
long long dc;
for(j=1;j<=21;j++)
{
dt=ans[t][j-1];
ans[t][j]=ans[dt][j-1];
}
}
}
}
}
inline int swim(int x,int y)
{
while(deep[x]!=deep[y])
{
int i=0;
while(deep[ans[y][i]]>deep[x])
i++;
if(i!=0)
i--;
y=ans[y][i];
}
return y;
}
inline long long lca(int x,int y)
{
if(deep[x]>deep[y])
{
int t=x;
x=y;
y=t;
}
y=swim(x,y);
int i=21;
while(x!=y)
{
while(ans[x][i]==ans[y][i]&&i>0)
i--;
x=ans[x][i];
y=ans[y][i];
}
return x;
}
//-------------------------LCA
int col[200001],col1[200001];
int tot;
int dline[300001];
int ld[200001],rd[200001];
int pos[200001];
inline bool cmp1(que x,que y)
{
if(pos[x.u]==pos[y.u])
{
if(x.v<y.v)
return true;
else if(x.v==y.v&&x.t<y.t)
return true;
return false;
}
if(pos[x.u]<pos[y.u])
return true;
return false;
}
inline bool cmp2(que x,que y)
{
if(x.p<y.p)
return true;
return false;
}
inline void dfsx(int d)
{
int i,j;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(!v[t])
{
v[t]=true;
tot++;
dline[tot]=t;
ld[t]=tot;
dfsx(t);
tot++;
dline[tot]=t;
rd[t]=tot;
}
}
}
long long sum,sa[100001];
inline void reverse(int x)
{
if(!v[x])
{
v[x]=true;
sa[col[x]]++;
sum+=w[sa[col[x]]]*val[col[x]];
}
else
{
v[x]=false;
sum-=w[sa[col[x]]]*val[col[x]];
sa[col[x]]--;
}
}
inline void decchange(int x)
{
if(v[c[x].x])
{
sum-=w[sa[c[x].t]]*val[c[x].t];
sa[c[x].t]--;
sa[c[x].s]++;
sum+=w[sa[c[x].s]]*val[c[x].s];
}
col[c[x].x]=c[x].s;
}
inline void incchange(int x)
{
if(v[c[x].x])
{
sum-=w[sa[c[x].s]]*val[c[x].s];
sa[c[x].s]--;
sa[c[x].t]++;
sum+=w[sa[c[x].t]]*val[c[x].t];
}
col[c[x].x]=c[x].t;
}
int main()
{
// freopen("park.in","r",stdin);
// freopen("park.out","w",stdout);
int n,q,m;
scanf("%d%d%d",&n,&q,&m);
int i;
int s,t;
for(i=1;i<=q;i++)
scanf("%lld",&val[i]);
for(i=1;i<=n;i++)
scanf("%lld",&w[i]);
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
}
for(i=1;i<=n;i++)
{
scanf("%d",&col[i]);
col1[i]=col[i];
}
bfs(1);
memset(v,false,sizeof(v));
v[1]=true;
tot++;
dline[1]=1;
ld[1]=1;
dfsx(1);
tot++;
dline[tot]=1;
rd[1]=tot;
//double xtx=1.8/3.0;
int nt=int(sqrt(tot));
for(i=1;i<=tot;i++)
pos[i]=(i-1)/nt+1;
int x;
int p1=0,p2=0;
for(i=1;i<=m;i++)
{
scanf("%d",&x);
if(x==0)
{
p2++;
scanf("%d%d",&c[p2].x,&c[p2].t);
c[p2].s=col1[c[p2].x];
col1[c[p2].x]=c[p2].t;
}
else
{
p1++;
scanf("%d%d",&ask[p1].u,&ask[p1].v);
if(ld[ask[p1].u]>ld[ask[p1].v])
swap(ask[p1].u,ask[p1].v);
ask[p1].u=rd[ask[p1].u];
ask[p1].v=ld[ask[p1].v];
if(ask[p1].u>=ask[p1].v)
ask[p1].u=ld[dline[ask[p1].u]];
ask[p1].p=p1;
ask[p1].t=p2;
}
}
sort(ask+1,ask+1+p1,cmp1);
memset(v,false,sizeof(v));
int l=ask[i].u,r=ask[i].u-1;
int time=0;
for(i=1;i<=p1;i++)
{
while(l<ask[i].u)
{
reverse(dline[l]);
l++;
}
while(l>ask[i].u)
{
l--;
reverse(dline[l]);
}
while(r<ask[i].v)
{
r++;
reverse(dline[r]);
}
while(r>ask[i].v)
{
reverse(dline[r]);
r--;
}
while(time>ask[i].t)
{
decchange(time);
time--;
}
while(time<ask[i].t)
{
time++;
incchange(time);
}
t=lca(dline[l],dline[r]);
int flag=false;
if(dline[ask[i].u]!=t&&dline[ask[i].v]!=t)
{
reverse(t);
flag=true;
}
ask[i].x=sum;
if(flag)
reverse(t);
}
sort(ask+1,ask+1+p1,cmp2);
for(i=1;i<=p1;i++)
printf("%lld\n",ask[i].x);
return 0;
}