タイトル
トピックリンク:https://www.luogu.com.cn/problem/P4074
Candylandお菓子公園があり、公園だけでなく、美しい風景、楽しい乗り物があり、につながった多くの無料キャンディ配布ポイントがあり、公園には多くの貪欲の子供たちのお菓子を再生します。
キャンディで構成公園の非常に特異な構造、される\(N \) 、各ツアーはポイントで発行されたお菓子をツアードット持って、我々はポイント数を訪問する変えることができますです\(1 \)へ(N \)\。そこ\(\ N-) - \(1 \)双方向の道路がこれらの観光スポットを接続し、全体のキャンディー公園が接続されていることは、他のすべての観光スポットにはこれらの道路を経由して到達することができ、公園内の任意の点から始まるツアーです。 。
種類公園によって発行されたキャンディキャンディは、全体の非常に豊富です\(M \)種、その数はなかった\(1 \)に(M \)\。それぞれのお菓子は、特定のお菓子で発行され、当社発行の\(C_I \)を表現するために(\ i)を\観光スポットのキャンディ数。
観光客をプレイするために公園に来て戻って好きではない、彼らは常にツアーの特定のポイントから開始遠足のための別の特定のポイントに移動し、途中の観光スポットを観光し、このルートは一意である必要があります。彼らはあなたがお菓子の種類に対応したものを楽しむことができ、各ツアーの後を指します。
私はお菓子の異なるタイプの程度は異なっているが大好きです。来場者の得点からのフィードバックによると、私たちはおいしいお菓子インデックスを得た、\(I \)おいしいお菓子インデックスの種類\(V_I \) 。また、繰り返しお菓子の同じ種類を楽しむ男が、彼は確かにいくつかの疲れがあると思うだろう。統計情報を定量化するためによると、私たちは観光客を得た\(I \)時間はキャンディ新奇性指数の特定の種類を楽しむ\(W_iを\) 。最初の男\(I \)回最初の味がする\(jは\)お菓子の種類は、その後、彼の喜び指数\(H \)は、すなわち、製品に対応する新しいおいしいインデックスインデックスに増加します(V_j \)\ × \(W_i \) 。公園を訪れる喜びインデックスの観光客は、最終的に製品の合計になります。
もちろん、それぞれのお菓子の配布ポイントが発行されている公園でお菓子の種類は、必ずしも石で設定されていません。時には、発行ポイントのいくつかのキャンディキャンディの種類は、(それだけになります変更される可能性があり、\(M \)訪問者は、常に驚きを感じる許可することを目指し、種の一種)。
スタッフキャンディーA小さな公園は、最近のデータによると、公園プレイパーク喜び指数の各訪問者の統計というタスクを受け取りました。小さいながらもデジタルを参照するには数学が得意では私は小さなAの親友として、あなたは彼を助けることを決めた、めまいを感じた混雑しました。
思考
そうモクコレクションは、(あなたの手を練習し、チームベースでノック、長い時間のためにチームをノックしないでください
木のMoブラケットチーム一般的なメンテナンスシーケンス、間隔\([L、R] \ ) 内のポイントは場合にのみポイント貢献\( [L、R] \)だけ登場回。想像\(X \)サブツリートラバーサルが完了するとバック、\(Xは\)第二時間を横断するが、この時間\(X \)パスではない。
したがって、各点の数が間隔内に発生する記録するマークを作成する。次に置くタイムスタンプ、修正液。
\(T \)取る\(N ^ {\ FRAC { 2} { 3}} \)する際の複雑さが\(O(N ^ {\ FRAC。5} {3} {})\) 。
コード醜い。チームのMo MERGE文、それが知られているので、はるかに高速になります。
コード
#pragma GCC optimize("Ofast","inline")
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define reg register
using namespace std;
typedef long long ll;
const int N=200010,LG=20;
int head[N],pos[N],st[N],nd[N],cnt[N],v[N],w[N],c[N],a[N],f[N][LG+1],dep[N];
int n,m,Q,Q1,Q2,T,tot;
bool flag[N];
ll ans,Ans[N];
inline int read()
{
int d=0; char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d;
}
struct Query
{
int l,r,t,num;
}ask[N];
inline bool operator < (const Query &a,const Query &b)
{
return pos[a.l]^pos[b.l] ? a.l<b.l : pos[a.l]&1 ? a.r<b.r : a.r>b.r;
}
struct Change
{
int x,y;
}chg[N];
struct edge
{
int next,to;
}e[N*2];
inline bool cmp(Query x,Query y)
{
if (pos[x.l]<pos[y.l]) return 1;
if (pos[x.l]>pos[y.l]) return 0;
return x.r<y.r;
}
inline void add(int from,int to)
{
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
inline void dfs(int x,int fa)
{
a[++tot]=x; st[x]=tot; pos[tot]=tot/T;
f[x][0]=fa; dep[x]=dep[fa]+1;
for (reg int i=1;i<=LG;i++)
f[x][i]=f[f[x][i-1]][i-1];
for (reg int i=head[x];~i;i=e[i].next)
if (e[i].to!=fa) dfs(e[i].to,x);
a[++tot]=x; nd[x]=tot; pos[tot]=tot/T;
}
inline int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
for (reg int i=LG;i>=0;i--)
if (dep[f[x][i]]>=dep[y]) x=f[x][i];
if (x==y) return x;
for (reg int i=LG;i>=0;i--)
if (f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void ins(int x)
{
ans+=1LL*v[c[x]]*w[++cnt[c[x]]];
flag[x]^=1;
}
inline void del(int x)
{
ans-=1LL*v[c[x]]*w[cnt[c[x]]--];
flag[x]^=1;
}
inline void solve(int x)
{
(flag[x]^=1) ? ans+=1LL*v[c[x]]*w[++cnt[c[x]]] : ans-=1LL*v[c[x]]*w[cnt[c[x]]--];
}
inline void update(int i)
{
if (flag[chg[i].x])
{
int y=chg[i].y,col=c[chg[i].x];
ans=ans-1LL*v[col]*w[cnt[col]--]+1LL*v[y]*w[++cnt[y]];
}
swap(chg[i].y,c[chg[i].x]);
}
int main()
{
memset(head,-1,sizeof(head));
n=read(); m=read(); Q=read();
T=pow(n,2.0/3);
for (reg int i=1;i<=m;i++) v[i]=read();
for (reg int i=1;i<=n;i++) w[i]=read();
for (reg int i=1,x,y;i<n;i++)
{
x=read(); y=read();
add(x,y); add(y,x);
}
for (reg int i=1;i<=n;i++) c[i]=read();
tot=0; dfs(1,0);
for (reg int i=1,type;i<=Q;i++)
{
type=read();
if (!type)
{
Q2++;
chg[Q2].x=read(); chg[Q2].y=read();
}
else
{
Q1++;
ask[Q1].t=Q2; ask[Q1].num=Q1;
int x=read(),y=read(),p=lca(x,y);
if (st[x]>st[y]) swap(x,y);
if (p==x || p==y)
ask[Q1].l=st[x],ask[Q1].r=st[y];
else
ask[Q1].l=nd[x],ask[Q1].r=st[y];
}
}
sort(ask+1,ask+1+Q1);
for (reg int l=1,r=0,t=0,i=1;i<=Q1;i++)
{
while (l<ask[i].l) solve(a[l++]);
while (l>ask[i].l) solve(a[--l]);
while (r<ask[i].r) solve(a[++r]);
while (r>ask[i].r) solve(a[r--]);
for (;t<ask[i].t;t++) update(t+1);
for (;t>ask[i].t;t--) update(t);
int p=lca(a[l],a[r]);
if (a[l]!=p && a[r]!=p) ins(p);
Ans[ask[i].num]=ans;
if (a[l]!=p && a[r]!=p) del(p);
}
for (reg int i=1;i<=Q1;i++)
printf("%lld\n",Ans[i]);
return 0;
}