UOJ #58 糖果公园

Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩。

糖果公园的结构十分奇特,它由 n 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 1 至 n。有 n1条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。

糖果公园所发放的糖果种类非常丰富,总共 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,则 1xn,1ym,表示编号为 x 的游览点发放的糖果类型改为 y;

若 t 为 1,则 1x,yn,表示对出发点为 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

限制与约定

对于所有的数据,1vi,wi106,1ai,bin,1cim,w1,w2,,wn 是非递增序列,即对任意 1<in,满足 wiwi1。

测试点编号nmq其它限制
1202020
2200020002000
3100001000010000
48000010080000没有修改操作;给出的图构成一条链
59000010090000
6800008000080000没有修改操作
7900009000090000
8800008000080000给出的图构成一条链
9900009000090000
10100000100000100000

祝大家一遍 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 }

 

转载于:https://www.cnblogs.com/LoveYayoi/p/6745435.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值