[BZOJ3052][UOJ#58][WC2013]糖果公园

试题描述

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,分别表示游览点个数、糖果种类数和操作次数。

第二行包含 m 个正整数 v1,v2,…,vm。

第三行包含 n 个正整数 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 的操作输出一行,用一个正整数表示答案。

输入示例


输出示例


数据规模及约定

对于所有的数据,1≤vi,wi≤106,1≤ai,bi≤n,1≤ci≤m,w1,w2,…,wn 是非递增序列,即对任意 1<i≤n,满足 wi≤wi−1

题解

树上带修莫队,其实就是对树分块之后将每个询问 (u, v) 变成三元组 (u, v, t)(表示当前已经进行了前 t 个修改),然后按照 u 所在块为第一关键字,v 所在块为第二关键字,t 为第三关键字排序。接下来暴力做就好了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
#define maxq 100010
#define maxlog 18
#define LL long long int n, C, m, head[maxn], nxt[maxm], to[maxm], colv[maxn], timv[maxn], col[maxn]; void AddEdge(int a, int b) {
to[++m] = b; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; nxt[m] = head[a]; head[a] = m;
return ;
} int Bsiz, S[maxn], top, cb, blid[maxn];
int fa[maxn], dep[maxn], clo, mnp[maxlog][maxn<<1], dfn[maxn];
void build(int u) {
mnp[0][dfn[u] = ++clo] = u;
int bot = top;
for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa[u]) {
fa[to[e]] = u; dep[to[e]] = dep[u] + 1;
build(to[e]);
mnp[0][++clo] = u;
if(top - bot >= Bsiz) {
cb++;
while(top > bot) blid[S[top--]] = cb;
}
}
S[++top] = u;
return ;
}
int Log[maxn<<1];
void rmq_init() {
Log[1] = 0;
for(int i = 2; i <= clo; i++) Log[i] = Log[i>>1] + 1;
for(int j = 1; (1 << j) <= clo; j++)
for(int i = 1; i + (1 << j) - 1 <= clo; i++) {
int a = mnp[j-1][i], b = mnp[j-1][i+(1<<j-1)];
mnp[j][i] = dep[a] < dep[b] ? a : b;
}
return ;
}
int lca(int a, int b) {
int l = dfn[a], r = dfn[b];
if(l > r) swap(l, r);
int t = Log[r-l+1];
a = mnp[t][l]; b = mnp[t][r-(1<<t)+1];
return dep[a] < dep[b] ? a : b;
} int q, cc, cq;
LL Ans[maxq];
struct Cmd {
int id, col, clst;
Cmd() {}
Cmd(int _1, int _2, int _3): id(_1), col(_2), clst(_3) {}
} cs[maxq];
struct Que {
int u, v, t, id;
Que() {}
Que(int _1, int _2, int _3, int _4): u(_1), v(_2), t(_3), id(_4) {}
bool operator < (const Que& t) const {
if(blid[u] != blid[t.u]) return blid[u] < blid[t.u];
if(blid[v] != blid[t.v]) return blid[v] < blid[t.v];
return this->t < t.t;
}
} qs[maxq]; int U, V, T, tot[maxn];
LL ans;
bool tag[maxn];
void rev(int u) {
if(tag[u]) ans -= (LL)timv[tot[col[u]]--] * colv[col[u]];
else ans += (LL)timv[++tot[col[u]]] * colv[col[u]];
tag[u] ^= 1;
return ;
}
void change(int& node, int tar) {
int c = lca(node, tar), To = tar;
while(node != c) rev(node), node = fa[node];
while(tar != c) rev(tar), tar = fa[tar];
node = To;
return ;
} int main() {
n = read(); C = read(); q = read();
for(int i = 1; i <= C; i++) colv[i] = read();
for(int i = 1; i <= n; i++) timv[i] = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read();
AddEdge(a, b);
}
for(int i = 1; i <= n; i++) col[i] = read();
Bsiz = pow(n, 2.0 / 3);
build(1);
while(top) blid[S[top--]] = cb;
rmq_init(); for(int i = 1; i <= q; i++) {
int tp = read();
if(!tp) {
int id = read(), co = read();
cs[++cc] = Cmd(id, co, col[id]);
col[id] = co;
}
else {
int u = read(), v = read();
cq++; qs[cq] = Que(u, v, cc, cq);
}
}
for(int i = cc; i; i--) col[cs[i].id] = cs[i].clst;
sort(qs + 1, qs + cq + 1); U = V = tot[col[1]] = tag[1] = 1; T = 0; ans = (LL)colv[col[1]] * timv[1];
for(int i = 1; i <= cq; i++) {
rev(lca(U, V)); rev(lca(qs[i].u, qs[i].v));
change(U, qs[i].u);
change(V, qs[i].v);
while(T < qs[i].t) {
T++;
int u = cs[T].id;
if(tag[u]) ans -= (LL)timv[tot[col[u]]--] * colv[col[u]];
col[u] = cs[T].col;
if(tag[u]) ans += (LL)timv[++tot[col[u]]] * colv[col[u]];
}
while(T > qs[i].t) {
int u = cs[T].id;
if(tag[u]) ans -= (LL)timv[tot[col[u]]--] * colv[col[u]];
col[u] = cs[T].clst;
if(tag[u]) ans += (LL)timv[++tot[col[u]]] * colv[col[u]];
T--;
}
Ans[qs[i].id] = ans;
} for(int i = 1; i <= cq; i++) printf("%lld\n", Ans[i]); return 0;
}

[BZOJ3052][UOJ#58][WC2013]糖果公园的更多相关文章

  1. BZOJ3052/UOJ#58 [wc2013]糖果公园 莫队 带修莫队 树上莫队

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3052.html 题目传送门 - BZOJ3052 题目传送门 - UOJ#58 题意 给定一棵树,有 ...

  2. BZOJ3052 & UOJ58:[WC2013]糖果公园——题解

    http://uoj.ac/problem/58 http://www.lydsy.com/JudgeOnline/problem.php?id=3052 输入格式 输出格式 input 4 3 5 ...

  3. 【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队

    [BZOJ3052][wc2013]糖果公园 Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 ...

  4. bzoj 3052: [wc2013]糖果公园 带修改莫队

    3052: [wc2013]糖果公园 Time Limit: 250 Sec  Memory Limit: 512 MBSubmit: 506  Solved: 189[Submit][Status] ...

  5. 洛谷 P4074 [WC2013]糖果公园 解题报告

    P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...

  6. AC日记——[WC2013]糖果公园 cogs 1817

    [WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...

  7. COGS1817. [WC2013]糖果公园

    1817. [WC2013]糖果公园 ★★★☆   输入文件:park.in   输出文件:park.out   简单对比时间限制:8 s   内存限制:512 MB [题目描述] Candyland ...

  8. BZOJ3052:[WC2013]糖果公园(树上莫队)

    Description Input Output Sample Input 4 3 51 9 27 6 5 12 33 13 41 2 3 21 1 21 4 20 2 11 1 21 4 2 Sam ...

  9. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

随机推荐

  1. Vijos p1688 病毒传递 树形DP

    https://vijos.org/p/1688 看了下别人讨论的题解才想到的,不过方法和他的不同,感觉它的是错的.(感觉.感觉) 首先N只有1000, 如果能做到暴力枚举每一个节点,然后O(N)算出 ...

  2. Hadoop工作流--JobControl(五)

    不多说,直接上干货! 这只是部分,做个引子. 未完,待续!

  3. markdown快捷键(转)

    markdown快捷键 GLYPH NAME COMMAND Command, Cmd, Clover, (formerly) Apple ALT Option, Opt, (Windows) Alt ...

  4. 基于 Web 的 Go 语言 IDE - Wide 1.5.0 发布!

    Wide 是什么 Wide 是一个基于 Web 的 Go 语言团队 IDE. 在线开发:打开浏览器就可以进行开发.全快捷键 智能提示:代码自动完成.查看表达式.编译反馈.Lint 实时运行:极速编译. ...

  5. Android CursorAdapter的使用

    CursorAdapter继承于BaseAdapter,为Cursor和ListView连接提供了桥梁. 首先看一下CursorAdapter的部分源码: /** * @see android.wid ...

  6. layer设置弹出全屏

    //弹出即全屏 var index = layer.open({ type: , content: 'http://www.layui.com', area: ['300px', '195px'], ...

  7. 解决./mysql-bin.index’ not found (Errcode: 13)

    问题出现在升级php版本以后,网站无法连接数据库,phpMyAdmin无法登录: 然后尝试开启mysql,/etc/init.d/mysqld start ,提示: Starting MySQL. E ...

  8. 应用-如何使不同的企业使用独自的数据源。使用ejb3.0+jboss6.2EAP+JPA

    摘要:                如何使不同的企业使用独自的数据源.使用ejb3.0+jboss6.2EAP+JPA10C应用系统被多个企业同时使用,为了提供个性化服务,如何使不同的企业使用独自的 ...

  9. toast插件的简单封装(样式适用pc后台管理系统的场景)

    直接分三个步骤吧: 1.手写一个toast.vue组件 <template> <transition name="toast-fade"> <div ...

  10. cnbeta新闻资讯第三方客户端应用

    该源码案例是一个cnbeta第三方客户端应用案例,作者ywwxhz,源码cnBeta-reader,cnbeta 的 Android 客户端项目. 源码下载: http://code.662p.com ...