传送门:http://uoj.ac/problem/58
思路:果断树上莫队模板,果断看的题解,,关于时间作为第三维推来推去idea还是极好的,弄了好久就因为不明白出战入站序的性质,,,反省,而且被vfk讲晕了,,明显他的集合标准差是另一种直接在树上做的写法,还是出战入站序好用,,,本来狂WA不止,,原来是没开LL,改了还是WA,,睡了,,第二天微机课,,改了快的大小,,仍然WA,不得已看了标程,,然而,,,就把一个内容改写成了函数,,就A了,,,什么玩意,,我明明没动程序好吧,,,就是不明白啊,,,貌似还有块状树的做法,有些部分分的做法也是值得借鉴的,,,
未完待续(非常重要)
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 100000
using namespace std;
typedef long long LL;
struct edge{ int nxt,point,v;};
struct node { int t,x,y,id; LL ans;};
struct data{ int num,last,now;};
edge e[(N<<1)+5];
node que1[(N<<1)+5];
data que2[(N<<1)+5];
int n,m,q,cnt,cnt1,cnt2,time1;
int v[N+5],w[N+5],a[N+5],b[N+5],dfn[(N<<1)+5],l[N+5],r[N+5],fa[N+5][25],deep[N+5],pos[(N<<1)+5],ts[N+5];
bool vis[N+5];
LL sum;
inline void addedge(int u1,int v1){
e[++cnt].nxt = e[u1].point; e[u1].point = cnt; e[cnt].v = v1;}
inline void insert(int u1,int v1){ addedge(u1,v1); addedge(v1,u1);}
inline bool cmp(node a,node b){
return ((pos[a.x] < pos[b.x])||(pos[a.x] == pos[b.x]&&pos[a.y]<pos[b.y])||
(pos[a.x] == pos[b.x]&&pos[a.y] == pos[b.y]&&a.t < b.t));}
inline bool cmp1(node a,node b){ return (a.id < b.id);}
inline int getnum(){
char c; int num;
while (!isdigit(c = getchar()));
num = c - '0';
while (isdigit(c = getchar())) num = 10 * num + c - '0';
return num;
}
void init(){
n = getnum(); m = getnum(); q = getnum(); cnt = 0;
for (int i = 1;i <= m; ++i) v[i] = getnum();
for (int i = 1;i <= n; ++i) w[i] = getnum();
for (int i = 1;i < n; ++i){
int u1 = getnum(),v1 = getnum();
insert(u1,v1);
}
for (int i = 1;i <= n; ++i) a[i] = b[i] = getnum();
time1 = 0;
}
inline void dfs(int x){
l[x] = ++time1; dfn[time1] = x;
for (int i = 1;i <= 20; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
for (int p = e[x].point;p; p = e[p].nxt)
if (!l[e[p].v]) {
deep[e[p].v] = deep[x] + 1; fa[e[p].v][0] = x;
dfs(e[p].v);}
r[x] = ++time1; dfn[time1] = x;
}
inline int LCA(int u,int v){
if (deep[u] < deep[v]) swap(u,v);
int ll = deep[u] - deep[v];
for (int i = 20;i >= 0; --i)
if (ll&(1<<i)) u = fa[u][i];
for (int i = 20;i >=0; --i)
if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
if (u != v) return fa[u][0];
return u;
}
void sort_it(){
int sz = (int)pow(time1, 2.0 / 3.0);
for (int i = 1;i <= time1; ++i) pos[i] = i/sz;
bool p;
int u1,v1;
cnt1 = cnt2 = 0;
for (int i = 1;i <= q; ++i){
p = getnum(); u1 = getnum(); v1 = getnum();
if (!p) que2[++cnt2].num = u1,que2[cnt2].last = b[u1],que2[cnt2].now = b[u1] = v1;
else{ int lca = LCA(u1,v1);
if (l[u1] > l[v1]) swap(u1,v1);
que1[++cnt1].t = cnt2;
que1[cnt1].id = cnt1;
if (lca != u1) que1[cnt1].x = r[u1], que1[cnt1].y = l[v1];
else que1[cnt1].x = l[u1],que1[cnt1].y = l[v1];}
}
sort(que1 + 1,que1 + cnt1 + 1,cmp);
// for (int i = 1;i <= cnt1; ++i) cout<<que1[i].id<<endl;
}
inline void change(int x){
if (vis[x]) sum = sum - (LL)v[a[x]]*w[ts[a[x]]--];
else sum = sum + (LL)v[a[x]]*w[++ts[a[x]]];
vis[x] ^= 1;
}
inline void modify(int s,int f){
if (vis[s])
{
change(s);
a[s] = f;
change(s);
}
else a[s] = f;
}
inline void change_time(int i){
for (int j = que1[i-1].t + 1;j <= que1[i].t; ++j) modify(que2[j].num,que2[j].now);
for (int j = que1[i-1].t ;j > que1[i].t; --j) modify(que2[j].num,que2[j].last);
}
void make_it(){
memset(vis,0,sizeof(vis));
memset(ts,0,sizeof(ts));
//for (int i = 1;i <= n; ++i) ts[a[i]] ++;
que1[0].t = 0; que1[0].x = 1; que1[0].y = 0; sum = 0;
for (int i = 1;i <= cnt1; ++i){
change_time(i);
//cout<<sum<<endl;
for (int j = que1[i-1].x - 1;j >= que1[i].x; --j) change(dfn[j]);
//for (int j = 1;j <= n; ++j) cout<<vis[j]<<" "; cout<<endl;
for (int j = que1[i-1].y + 1;j <= que1[i].y; ++j) change(dfn[j]);
//cout<<sum<<endl;
//for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl;
for (int j = que1[i-1].x;j < que1[i].x; ++j) change(dfn[j]);
//for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl;
for (int j = que1[i-1].y;j > que1[i].y; --j) change(dfn[j]);
//for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";cout<<endl;
//for (int j = 1;j <= n; ++j) cout<<vis[j]<<" ";
//cout<<endl;
//cout<<sum<<" ";
int u = dfn[que1[i].x],v = dfn[que1[i].y],lca = LCA(u,v);
if (u != lca && v != lca) change(lca);
que1[i].ans = sum;
//cout<<sum<<endl;
if (u != lca && v != lca) change(lca);
}
}
void DO_IT(){
dfs(1);
//for (int i = 1;i <= time; ++i) cout<<dfn[i]<<endl;
sort_it();
//for (int i = 1;i <= cnt1; ++i) cout<<que1[i].x<<" "<<que1[i].y<<" "<<que1[i].t<<" "<<endl;
make_it();
}
void print(){
sort(que1 + 1,que1 + cnt1 + 1,cmp1);
for (int i = 1;i <= cnt1; ++i) printf("%lld\n",que1[i].ans);
}
int main(){
init();
DO_IT();
print();
return 0;
}