【WC2013】糖果公园
Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩。
糖果公园的结构十分奇特,它由 nn 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 11 至 nn。有 n−1n−1 条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。
糖果公园所发放的糖果种类非常丰富,总共 mm 种,它们的编号依次为 11 至 mm。每一个糖果发放处都只发放某种特定的糖果,我们用 cici 来表示 ii 号游览点的糖果。
来到公园里游玩的游客都不喜欢走回头路,他们总是从某个特定的游览点出发前往另一个特定的游览点,并游览途中的景点,这条路线一定是唯一的。他们经过每个游览点,都可以品尝到一颗对应种类的糖果。
大家对不同类型的糖果的喜爱程度都不尽相同。根据游客们的反馈打分,我们得到了糖果的美味指数,第 ii 种糖果的美味指数为 vivi。另外,如果一位游客反复地品尝同一种类的糖果,他肯定会觉得有一些腻。根据量化统计,我们得到了游客第 ii 次品尝某类糖果的新奇指数 wiwi,如果一位游客第 ii 次品尝第 jj 种糖果,那么他的愉悦指数 HH 将会增加对应的美味指数与新奇指数的乘积,即 vjwivjwi。这位游客游览公园的愉悦指数最终将是这些乘积的和。
当然,公园中每个糖果发放点所发放的糖果种类不一定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 mm 种中的一种),这样的目的是能够让游客们总是感受到惊喜。
糖果公园的工作人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学不好的小 A 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。
输入格式
第一行包含三个正整数 n,m,qn,m,q,分别表示游览点个数、糖果种类数和操作次数。
第二行包含 mm 个正整数 v1,v2,…,vmv1,v2,…,vm。
第三行包含 nn 个正整数 w1,w2,…,wnw1,w2,…,wn。
第四行到第 n+2n+2 行,每行包含两个正整数 ai,biai,bi,表示这两个游览点之间有路径可以直接到达。
第 n+3n+3 行包含 nn 个正整数 c1,c2,…,cnc1,c2,…,cn。
接下来 qq 行,每行包含三个整数 t,x,yt,x,y,表示一次操作:
若 tt 为 00,则 1≤x≤n1≤x≤n,1≤y≤m1≤y≤m,表示编号为 xx 的游览点发放的糖果类型改为 yy;
若 tt 为 11,则 1≤x,y≤n1≤x,y≤n,表示对出发点为 xx,终止点为 yy 的路线询问愉悦指数。
输出格式
按照输入的先后顺序,对于每个 tt 为 11 的操作输出一行,用一个正整数表示答案。
样例一
input
4 3 5 1 9 2 7 6 5 1 2 3 3 1 3 4 1 2 3 2 1 1 2 1 4 2 0 2 1 1 1 2 1 4 2
output
84 131 27 84
bzoj没有权限号的小朋友只能去uoj辣!
树上莫队,我是先膜的黄学长代码才会写的……
然后压了几发常数,都没有第一次交快 =_= 天生自带大常数。。。
#include<cstdio> #include<algorithm> #define ll long long #define M 100001 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } int n,m,c[M],p[M],to=0,fa[M][30],l[M],d[M],num=0,nm=0,knm=0,be[M],de[M],q,nas=0,nch=0,pre[M],ti[M]; ll an=0,ans[M],v[M],w[M]; bool vi[M]; struct na{ int y,ne; }b[2*M+10]; const int ku=1000; inline void in(int x,int y){ b[++num].y=y;b[num].ne=l[x];l[x]=num; b[++num].y=x;b[num].ne=l[y];l[y]=num; } inline void dfs(int x){ int i; for (i=1;i<=17;i++) if (fa[fa[x][i-1]][i-1]) fa[x][i]=fa[fa[x][i-1]][i-1];else break; int bo=to; d[x]=++nm; for (i=l[x];i;i=b[i].ne) if (!de[b[i].y]){ de[b[i].y]=de[x]+1; fa[b[i].y][0]=x; dfs(b[i].y); if (to-bo>=ku){ knm++; while (to!=bo) be[p[to--]]=knm; } } p[++to]=x; } struct ask{ int x,y,t,id; }ba[M]; struct as{ int x,y,p; }bc[M]; inline bool cmp(ask x,ask y){ if (be[x.x]==be[y.x]) return d[x.y]<d[y.y]; return be[x.x]<be[y.x]; } inline void xo(int x){if (vi[x]) an-=w[ti[c[x]]]*v[c[x]],ti[c[x]]--;else ti[c[x]]++,an+=w[ti[c[x]]]*v[c[x]];vi[x]^=1;} inline void work(int x,int y){while (x!=y) if (de[x]>de[y]) xo(x),x=fa[x][0];else xo(y),y=fa[y][0];} inline void cha(int x,int y){if (vi[x]) xo(x),c[x]=y,xo(x);else c[x]=y;} inline int lca(int x,int y){ if (de[x]<de[y]) swap(x,y); for (int i=17;i>=0;i--) if (de[fa[x][i]]>=de[y]&&fa[x][i]) x=fa[x][i]; for (int i=17;i>=0;i--) if (fa[x][i]!=fa[y][i]&&fa[x][i]&&fa[y][i]) x=fa[x][i],y=fa[y][i]; if (x==y) return x; return fa[x][0]; } int main(){ int i,o,x,y,j; n=read();m=read();q=read(); for (i=1;i<=m;i++) v[i]=read(); for (i=1;i<=n;i++) w[i]=read(); for (i=1;i<n;i++) in(read(),read()); for (i=1;i<=n;i++) pre[i]=c[i]=read(); de[1]=1; dfs(1); for (i=1;i<=q;i++){ o=read();x=read();y=read(); if (o){ if (d[x]>d[y]) swap(x,y); nas++; ba[nas].x=x;ba[nas].y=y;ba[nas].t=nch;ba[nas].id=nas; }else{ nch++; bc[nch].x=x;bc[nch].y=y;bc[nch].p=pre[x];pre[x]=y; } } sort(ba+1,ba+1+nas,cmp); for (i=1;i<=ba[1].t;i++) cha(bc[i].x,bc[i].y); work(ba[1].x,ba[1].y); o=lca(ba[1].x,ba[1].y); xo(o);ans[ba[1].id]=an;xo(o); for (i=2;i<=nas;i++){ for (j=ba[i-1].t+1;j<=ba[i].t;j++) cha(bc[j].x,bc[j].y); for (j=ba[i-1].t;j>ba[i].t;j--) cha(bc[j].x,bc[j].p); work(ba[i-1].x,ba[i].x); work(ba[i-1].y,ba[i].y); o=lca(ba[i].x,ba[i].y); xo(o);ans[ba[i].id]=an;xo(o); } for (i=1;i<=nas;i++) printf("%lld\n",ans[i]); }