UOJ #58 糖果公园
Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩。
糖果公园的结构十分奇特,它由 n 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 1 至 n。有 n−1条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。
糖果公园所发放的糖果种类非常丰富,总共 m 种,它们的编号依次为 1 至 m。每一个糖果发放处都只发放某种特定的糖果,我们用 ci 来表示 i 号游览点的糖果。
来到公园里游玩的游客都不喜欢走回头路,他们总是从某个特定的游览点出发前往另一个特定的游览点,并游览途中的景点,这条路线一定是唯一的。他们经过每个游览点,都可以品尝到一颗对应种类的糖果。
大家对不同类型的糖果的喜爱程度都不尽相同。根据游客们的反馈打分,我们得到了糖果的美味指数,第 i 种糖果的美味指数为 vi。另外,如果一位游客反复地品尝同一种类的糖果,他肯定会觉得有一些腻。根据量化统计,我们得到了游客第 i 次品尝某类糖果的新奇指数 wi,如果一位游客第 i 次品尝第 j 种糖果,那么他的愉悦指数 H 将会增加对应的美味指数与新奇指数的乘积,即 vjwi。这位游客游览公园的愉悦指数最终将是这些乘积的和。
当然,公园中每个糖果发放点所发放的糖果种类不一定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 m 种中的一种),这样的目的是能够让游客们总是感受到惊喜。
糖果公园的工作人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学不好的小 A 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。
输入格式
第一行包含三个正整数 n,m,q,分别表示游览点个数、糖果种类数和操作次数。
第二行包含 mm 个正整数 v1,v2,…,vm。
第三行包含 nn 个正整数 w1,w2,…,wn。
第四行到第 n+2 行,每行包含两个正整数 ai,bi,表示这两个游览点之间有路径可以直接到达。
第 n+3 行包含 n 个正整数 c1,c2,…,cn。
接下来 q 行,每行包含三个整数 t,x,y,表示一次操作:
若 t 为 0,则 1≤x≤n,1≤y≤m,表示编号为 x 的游览点发放的糖果类型改为 y;
若 t 为 1,则 1≤x,y≤n,表示对出发点为 x,终止点为 y 的路线询问愉悦指数。
输出格式
按照输入的先后顺序,对于每个 t 为 1 的操作输出一行,用一个正整数表示答案。
样例一
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
限制与约定
对于所有的数据,1≤vi,wi≤106,1≤ai,bi≤n,1≤ci≤m,w1,w2,…,wn 是非递增序列,即对任意 1<i≤n,满足 wi≤wi−1。
测试点编号 | n | m | q | 其它限制 |
---|---|---|---|---|
1 | ≤20 | ≤20 | ≤20 | 无 |
2 | ≤2000 | ≤2000 | ≤2000 | |
3 | ≤10000 | ≤10000 | ≤10000 | |
4 | ≤80000 | ≤100 | ≤80000 | 没有修改操作;给出的图构成一条链 |
5 | ≤90000 | ≤100 | ≤90000 | |
6 | ≤80000 | ≤80000 | ≤80000 | 没有修改操作 |
7 | ≤90000 | ≤90000 | ≤90000 | |
8 | ≤80000 | ≤80000 | ≤80000 | 给出的图构成一条链 |
9 | ≤90000 | ≤90000 | ≤90000 | |
10 | ≤100000 | ≤100000 | ≤100000 | 无 |
祝大家一遍 AC,求不虐萌萌哒测评机!
时间限制:8s
空间限制:512MB
真是卡OJ神题,我这道题加起来大概卡了UOJ有10min
树上带修莫队,按照DFS序分块或者王室联邦都行,好像王室联邦会更快
移动端点就是修改两条链,只要不断的往LCA爬,将路径上的点存在性取反就行了,不用讨论,但要记得LCA只翻转一次
记得排序的时候按照所属块排序,左右端点都是,不要写出右端点直接比较这种东西来了
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <string> 6 #include <cstring> 7 #include <cmath> 8 #include <map> 9 #include <stack> 10 #include <set> 11 #include <vector> 12 #include <queue> 13 #include <time.h> 14 #define eps 10e-7 15 #define INF 0x3f3f3f3f 16 #define MOD 1000000007 17 #define rep0(j,n) for(int j=0;j<n;++j) 18 #define rep1(j,n) for(int j=1;j<=n;++j) 19 #define pb push_back 20 #define set0(n) memset(n,0,sizeof(n)) 21 #define ll long long 22 #define iter(i,v) for(edge *i = head[v];i;i = i->nxt) 23 #define max(a,b) (a>b?a:b) 24 #define min(a,b) (a<b?a:b) 25 //#define OJ 26 using namespace std; 27 char BUF[10000000], *buf; 28 int read() { 29 int x = 0; 30 while (!isdigit(*buf)) { buf++; } 31 while (isdigit(*buf)) { x = x * 10 + *buf++ - '0'; } 32 return x; 33 } 34 char get_ch() { 35 char c = getchar(); 36 while (!isalpha(c)) c = getchar(); 37 return c; 38 } 39 const int MAXINT = 100010; 40 const int MAXNODE = 100010; 41 ll ans, w[MAXNODE], ps_w[MAXINT], qa[MAXINT]; 42 int st[18][MAXNODE*4]={},seq[MAXNODE*4]={},cnt_seq=0,fst[MAXNODE]={},max_p2[262145]={},no[MAXNODE],stk[MAXNODE],top=0,cnt_bl=1; 43 int dfn[MAXNODE]={}, cnt_dfn=0, bl[MAXNODE]={}, n=0, m=0, v[MAXINT]={}, c[MAXNODE]={}, dep[MAXNODE]={}, in_ans[MAXNODE]={}, fa[MAXNODE]={}, cnt_eg, sz_b, q, cnt_cd[MAXINT]={}, cnt_mdf = -1, cnt_qr; 44 struct edge { 45 int u, v; 46 edge *nxt; 47 edge(int _u, int _v, edge *_nxt) { 48 u = _u; v = _v; nxt = _nxt; 49 } 50 edge() {} 51 }*head[MAXNODE], mp[MAXNODE * 2]; 52 struct op { 53 int tp, x, y, lstc, no; 54 op(int _x, int _y) { 55 tp = 1; 56 x = _x; 57 y = _y; 58 } 59 op(int lst, int _x, int _y, int _no) { 60 lstc = lst; 61 tp = 0; 62 //if (dfn[_x] > dfn[_y]) swap(_x, _y); 63 x = _x; 64 y = _y; 65 no = _no; 66 } 67 op() {} 68 }mdf[MAXINT], qr[MAXINT]; 69 int cmp(const op &a, const op &b) { 70 if(bl[a.x]==bl[b.x]&&bl[a.y]==bl[b.y]) {if(bl[a.x]&1)return a.lstc<b.lstc; else return a.lstc>b.lstc;} 71 if(bl[a.x]==bl[b.x]) {if(bl[a.x]&1) return bl[a.y]<bl[b.y]; else return bl[a.y]>bl[b.y];} 72 return bl[a.x] < bl[b.x]; 73 } 74 inline void rev(int); 75 inline void add(int); 76 inline void remove(int); 77 inline void add(op&); 78 inline void remove(op&); 79 inline void add_edge(int, int); 80 inline void get_st(); 81 inline void get_input(); 82 inline void work(); 83 inline void solve(int,int); 84 inline int get_lca(int, int); 85 //inline void dfs(int, int); 86 inline int dfs(int, int); 87 int main() { 88 //freopen("in.txt", "r", stdin); 89 //freopen("out.tle", "w", stdout); 90 for(int i=0;i<=17;i++){ 91 for (int j=(1<<i);j<(1<<(i+1));j++){ 92 max_p2[j]=i; 93 } 94 } 95 get_input(); 96 get_st(); 97 work(); 98 //printf("%d\n",clock()); 99 return 0; 100 } 101 inline void rev(int p) { 102 if (in_ans[p]) { 103 in_ans[p] = 0; 104 ans -= w[cnt_cd[c[p]]] * v[c[p]]; 105 cnt_cd[c[p]]--; 106 } 107 else { 108 in_ans[p] = 1; 109 cnt_cd[c[p]]++; 110 ans += w[cnt_cd[c[p]]] * v[c[p]]; 111 } 112 } 113 inline void solve(int p1,int p2){ 114 while(p1!=p2){ 115 dep[p1]>dep[p2]?(rev(p1),p1=fa[p1]):(rev(p2),p2=fa[p2]); 116 } 117 } 118 inline void work() { 119 rep0(i,cnt_qr) if(bl[qr[i].x]<bl[qr[i].y]) swap(qr[i].x,qr[i].y); 120 sort(qr, qr + cnt_qr, cmp); 121 int l, r, pl, pr, lca, lca2, pq = -1; 122 for (int i = pq; i > qr[0].lstc; i--) { 123 remove(mdf[i]); 124 } 125 for (int i = pq + 1; i <= qr[0].lstc; i++) { 126 add(mdf[i]); 127 } 128 pl = l = qr[0].x; 129 pr = r = qr[0].y; 130 lca = get_lca(l, r); 131 solve(pl,pr); 132 rev(lca); 133 qa[qr[0].no] = ans; 134 pq = qr[0].lstc; 135 rep1(i, cnt_qr - 1) { 136 for (int j = pq; j > qr[i].lstc; j--) { 137 remove(mdf[j]); 138 } 139 for (int j = pq + 1; j <= qr[i].lstc; j++) { 140 add(mdf[j]); 141 } 142 lca = get_lca(l, r); 143 lca2 = get_lca(qr[i].x, qr[i].y); 144 solve(l,qr[i].x); 145 solve(r,qr[i].y); 146 rev(lca); 147 rev(lca2); 148 l = qr[i].x; r = qr[i].y; 149 pq = qr[i].lstc; 150 qa[qr[i].no] = ans; 151 } 152 rep0(i, cnt_qr) { 153 printf("%lld\n", qa[i]); 154 } 155 } 156 inline void add_edge(int u, int v) { 157 mp[cnt_eg] = edge(u, v, head[u]); 158 head[u] = &mp[cnt_eg++]; 159 mp[cnt_eg] = edge(v, u, head[v]); 160 head[v] = &mp[cnt_eg++]; 161 } 162 inline void get_input() { 163 int tp, _u, _v; 164 BUF[fread(BUF, 1, 10000000, stdin)]=0; 165 buf = BUF; 166 n = read(); m = read(); q = read(); 167 sz_b = ceil(pow(n, 2.0 / 3.0))/2+1; 168 rep1(i, m) v[i] = read(); 169 rep1(i, n) w[i] = read(); 170 rep1(i, n) ps_w[i] += ps_w[i - 1] + w[i]; 171 rep1(i, n - 1) { 172 _u = read(); _v = read(); 173 add_edge(_u, _v); 174 } 175 dfs(1, 0); 176 while(top) bl[stk[--top]]=cnt_bl-1; 177 rep1(i, n) c[i] = read(); 178 rep0(i, q) { 179 tp = read(); _u = read(); _v = read(); 180 if (tp == 1) qr[cnt_qr] = op(cnt_mdf, _u, _v, cnt_qr), cnt_qr++; 181 else mdf[++cnt_mdf] = op(_u, _v); 182 } 183 } 184 /*inline void dfs(int p, int f) { 185 fa[p] = f; 186 dep[p] = dep[f] + 1; 187 no[cnt_dfn]=p; 188 dfn[p] = ++cnt_dfn; 189 bl[p] = dfn[p] / sz_b; 190 fst[p] = cnt_seq; 191 seq[cnt_seq++]=dfn[p]; 192 iter(i, p) { 193 if (i->v == f) continue; 194 dfs(i->v, p); 195 seq[cnt_seq++]=dfn[p]; 196 } 197 }*/ 198 inline int dfs(int p, int f) { 199 int sz=0,bt=top; 200 fa[p] = f; 201 dep[p] = dep[f] + 1; 202 no[cnt_dfn]=p; 203 dfn[p] = ++cnt_dfn; 204 //bl[p] = dfn[p] / sz_b; 205 fst[p] = cnt_seq; 206 seq[cnt_seq++]=dfn[p]; 207 iter(i, p) { 208 if (i->v == f) continue; 209 sz+=dfs(i->v, p); 210 seq[cnt_seq++]=dfn[p]; 211 if (top-bt>=sz_b){ 212 while(top!=bt) bl[stk[--top]]=cnt_bl; 213 cnt_bl++,sz=0; 214 } 215 } 216 stk[top++]=p; 217 return sz+1; 218 } 219 inline void get_st() { 220 rep0(i,cnt_seq) st[0][i]=seq[i]; 221 for (int i = 1; i <= 17; i++) 222 for (int j = 0; j < cnt_seq-(1<<i)+1; j++) 223 st[i][j] = min(st[i-1][j],st[i-1][j+(1<<(i-1))]); 224 } 225 inline int get_lca(int x, int y) { 226 x=fst[x];y=fst[y]; 227 if(x>y) swap(x,y); 228 int l = y-x+1; 229 return no[min(st[max_p2[l]][x],st[max_p2[l]][y-(1<<max_p2[l])+1])-1]; 230 } 231 inline void remove(int p) { 232 ans -= w[cnt_cd[p]] * v[p]; 233 cnt_cd[p]--; 234 } 235 inline void add(int p) { 236 cnt_cd[p]++; 237 ans += w[cnt_cd[p]] * v[p]; 238 } 239 inline void add(op& cg) { 240 //int f = get_lca(l, r), f1 = get_lca(l, cg.x), f2 = get_lca(r, cg.x); 241 cg.lstc = c[cg.x]; 242 c[cg.x] = cg.y; 243 if(in_ans[cg.x]){ 244 //if ((f == f1&&f2 == cg.x) || (f == f2&&f1 == cg.x)) { 245 ans -= w[cnt_cd[cg.lstc]] * v[cg.lstc]; 246 cnt_cd[cg.lstc]--; 247 cnt_cd[cg.y]++; 248 ans += w[cnt_cd[cg.y]] * v[cg.y]; 249 } 250 } 251 inline void remove(op& cg) { 252 //int f = get_lca(l, r), f1 = get_lca(l, cg.x), f2 = get_lca(r, cg.x); 253 c[cg.x] = cg.lstc; 254 //if ((f == f1&&f2 == cg.x) || (f == f2&&f1 == cg.x)) { 255 if(in_ans[cg.x]){ 256 ans -= w[cnt_cd[cg.y]] * v[cg.y]; 257 cnt_cd[cg.y]--; 258 cnt_cd[cg.lstc]++; 259 ans += w[cnt_cd[cg.lstc]] * v[cg.lstc]; 260 } 261 }