题目大意:给定一棵树,每个点有一个颜色,提供两种操作:
1.询问两点间路径上的Σv[a[i]]*w[k],其中a[i]代表这个点的颜色,k表示这个点是这种颜色第k次出现
2.修改某个点的颜色
VfleaKing的题解见 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
带修改莫队上树……如果不带修改就正常搞就好了
如果带修改的话,令块的大小为n^(2/3)
将询问排序时第一键值为左端点所在块,第二键值为右端点所在块,第三键值为询问时间
然后将一个询问跳到下一个的时候先改链上的点,然后处理修改
这样最后可以保证最坏复杂度为O(n^(5/3)) 强行不到O(n^2)……
记住TLE不一定是常数大或者死循环 很可能是莫队写挂了 建议TLE的好好检查一下
另外推荐在半夜刷这道题……不然容易引起民粪……
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
namespace IStream{
const int L=1<<15;
char buffer[L];
char *S,*T;
inline char Get_Char()
{
if(S==T)
{
T=(S=buffer)+fread(buffer,1,L,stdin);
if(S==T) return EOF;
}
return *S++;
}
inline int Get_Int()
{
int re=0;
char c;
do c=Get_Char(); while(c<'0'||c>'9');
while(c>='0'&&c<='9')
re=(re<<3)+(re<<1)+(c-'0'),c=Get_Char();
return re;
}
}
struct abcd{
int to,next;
}table[M<<1];
struct query{
int x,y,pos;
bool operator < (const query &Y) const;
}queries[M];
struct modification{
int x,from,to,pos;
}modifications[M];
int head[M],tot;
int n,m,q,B,end;bool flag;
int a[M],value[M],incuriosity[M];
int fa[M][20],belong[M],size[M],dpt[M],pos[M];
int cnt[M];bool v[M];long long now,ans[M];
bool query :: operator < (const query &Y) const
{
if(flag)
{
if(belong[x]!=belong[Y.x])
return belong[x]<belong[Y.x];
if(belong[y]!=belong[Y.y])
return belong[y]<belong[Y.y];
return pos < Y.pos;
}
else
{
if(belong[x]!=belong[Y.x])
return belong[x]<belong[Y.x];
return ::pos[y] < ::pos[Y.y];
}
}
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void DFS(int x)
{
int i;
static int cnt=0,T=0;
if(!fa[x][0]||size[belong[fa[x][0]]]==B)
size[ belong[x]=++cnt ]++;
else
size[ belong[x]=belong[fa[x][0]] ]++;
dpt[x]=dpt[fa[x][0]]+1;pos[x]=++T;
for(i=head[x];i;i=table[i].next)
if(table[i].to!=fa[x][0])
fa[table[i].to][0]=x,DFS(table[i].to);
}
int LCA(int x,int y)
{
int j;
if(dpt[x]<dpt[y])
swap(x,y);
for(j=17;j>=0;j--)
if(dpt[fa[x][j]]>=dpt[y])
x=fa[x][j];
if(x==y) return x;
for(j=17;j>=0;j--)
if(fa[x][j]!=fa[y][j])
x=fa[x][j],y=fa[y][j];
return fa[x][0];
}
void Change(int x)
{
v[x]^=1;
if(v[x]==1)
{
cnt[a[x]]++;
if(cnt[a[x]]>=1)
now+=(long long)value[a[x]]*incuriosity[cnt[a[x]]];
}
else
{
if(cnt[a[x]]>=1)
now-=(long long)value[a[x]]*incuriosity[cnt[a[x]]];
cnt[a[x]]--;
}
}
void Change(modification temp,bool flag)
{
if(flag) swap(temp.from,temp.to);
a[temp.x]=temp.to;
if(v[temp.x])
{
if(cnt[temp.from]>=1)
now-=(long long)value[temp.from]*incuriosity[cnt[temp.from]];
cnt[temp.from]--;
cnt[temp.to]++;
if(cnt[temp.to]>=1)
now+=(long long)value[temp.to]*incuriosity[cnt[temp.to]];
}
}
int main()
{
int i,j,x,y,p,temp,lca;
cin>>n>>m>>q;
for(i=1;i<=m;i++)
value[i]=IStream::Get_Int();
for(i=1;i<=n;i++)
incuriosity[i]=IStream::Get_Int();
for(i=1;i<n;i++)
{
x=IStream::Get_Int();
y=IStream::Get_Int();
Add(x,y);
Add(y,x);
}
for(i=1;i<=n;i++)
a[i]=IStream::Get_Int();
temp=0;
for(i=1;i<=q;i++)
{
p=IStream::Get_Int();
x=IStream::Get_Int();
y=IStream::Get_Int();
if(p==1)
{
if(pos[x]>pos[y])
swap(x,y);
queries[++temp].pos=temp;
queries[temp].x=x;
queries[temp].y=y;
}
else
{
flag=1;
modifications[++end].x=x;
modifications[end].from=a[x];
modifications[end].to=a[x]=y;
modifications[end].pos=temp;
}
}
q=temp;
if(flag)
B=static_cast<int>(pow(n,2.0/3.0)+1e-7);
else
B=static_cast<int>(sqrt(n)+1e-7);
DFS(1);
for(j=1;j<=17;j++)
for(i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
x=y=1;temp=end;
sort(queries+1,queries+q+1);
for(i=1;i<=q;i++)
{
lca=LCA(x,queries[i].x);
for(j=x;j!=lca;j=fa[j][0]) Change(j);
for(j=queries[i].x;j!=lca;j=fa[j][0]) Change(j);
lca=LCA(y,queries[i].y);
for(j=y;j!=lca;j=fa[j][0]) Change(j);
for(j=queries[i].y;j!=lca;j=fa[j][0]) Change(j);
lca=LCA(x=queries[i].x,y=queries[i].y);
Change(lca);
for(;temp>0 && modifications[temp].pos>=queries[i].pos ;temp--)
Change(modifications[temp],1);
for(;temp<end && modifications[temp+1].pos<queries[i].pos;temp++)
Change(modifications[temp+1],0);
ans[queries[i].pos]=now;
Change(lca);
}
for(i=1;i<=q;i++)
{
#ifdef ONLINE_JUDGE
printf("%lld\n",ans[i]);
#endif
#ifdef C_PoPoQQQ
printf("%I64d\n",ans[i]);
#endif
}
}