题目描述

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 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。

输入输出格式

输入格式:

从文件 park.in 中读入数据。

第一行包含三个正整数 \(n\), \(m\), \(q\), 分别表示游览点个数、 糖果种类数和操作次数。

第二行包含 \(m\) 个正整数 \(V_1,V_2,...,V_m\) 。

第三行包含 \(n\) 个正整数 \(W_1,W_2,...,W_n\) 。

第四行到第 \(n+2\) 行,每行包含两个正整数 \(A_i,B_i\) ,表示这两个游览点之间有路径可以直接到达。

第 \(n+3\) 行包含 \(n\) 个正整数 \(C_1,C_2,C_n\) 。

接下来 \(q\) 行, 每行包含三个整数 \(Type\), \(x\), \(y\),表示一次操作:

若 \(Type\) 为 \(0\),则 \(1 ≤ x ≤ n\), \(1 ≤ y ≤ m\),表示将编号为 \(x\) 的游览点发放的糖果类型改为 \(y\);

若 \(Type\) 为 \(1\),则 \(1 ≤ x, y ≤ n\),表示对出发点为 \(x\),终止点为 \(y\) 的路线询问愉悦指数。

输出格式:

输出到文件 park.out 中。

按照输入的先后顺序,对于每个 \(Type\) 为 \(1\) 的操作输出一行,用一个正整数表示答案。

输入输出样例

输入样例#1:

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

输出样例#1:

84
131
27
84

整体思路

树上莫队+带修莫队=树上带修莫队,如果不懂可以看这里

莫队添加数值时,添加的数值(添加的结点发的糖,记为\(c\))对答案的贡献为\(V_c × W_{cnt_c}\),在端点、修改点、lca暴力添加即可。删除亦然。

code:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 200200
#define ll long long
int cnt[maxn], aa[maxn], belong[maxn], inp[maxn], n, m, Q, ncnt, size, bnum, w[maxn], v[maxn], ccnt, qcnt;
int val[maxn], fa[maxn][30], depth[maxn], head[maxn], ecnt;
int fir[maxn], la[maxn], vis[maxn];
int l = 1, r = 0, t = 0;
ll now, ans[maxn];
struct edge {
int to, next;
} e[maxn];
void adde(int u, int v) {
e[++ecnt] = (edge){v, head[u]};
head[u] = ecnt;
e[++ecnt] = (edge){u, head[v]};
head[v] = ecnt;
}
void dfs(int x) {
aa[++ncnt] = x;
fir[x] = ncnt;
for(int k = head[x]; k; k = e[k].next) {
int to = e[k].to;
if(depth[to]) continue;
depth[to] = depth[x] + 1;
fa[to][0] = x;
for(int i = 1; (1 << i) <= depth[to]; ++i) fa[to][i] = fa[fa[to][i - 1]][i - 1];
dfs(to);
}
aa[++ncnt] = x;
la[x] = ncnt;
}
int getlca(int u, int v) {
if(depth[u] < depth[v]) swap(u, v);
for(int i = 20; i + 1; --i) if(depth[fa[u][i]] >= depth[v]) u = fa[u][i];
if(u == v) return u;
for(int i = 20; i + 1; --i) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
struct query {
int l, r, id, lca, t;
} q[maxn];
int cmp(query a, query b) {
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.r] ^ belong[b.r]) ? belong[a.r] < belong[b.r] : a.t < b.t );
}
inline void add(int pos) {
now += 1ll * v[val[pos]] * w[++cnt[val[pos]]];
}
inline void del(int pos) {
now -= 1ll * v[val[pos]] * w[cnt[val[pos]]--];
}
inline void work(int pos) {
vis[pos] ? del(pos) : add(pos);
vis[pos] ^= 1;
}
struct change {
int pos, val;
} ch[maxn];
void modify(int x) {
if(vis[ch[x].pos]) {
work(ch[x].pos);
swap(val[ch[x].pos], ch[x].val);
work(ch[x].pos);
}
else swap(val[ch[x].pos], ch[x].val);
}
#define isdigit(x) ((x) >= '0' && (x) <= '9')
inline int read() {
int res = 0;
char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
return res;
}
int main() {
n = read(), m = read(), Q = read();
for(int i = 1; i <= m; ++i) v[i] = read();
for(int i = 1; i <= n; ++i) w[i] = read();
for(int i = 1; i < n; ++i) {
int u = read(), v = read();
adde(u, v);
}
for(int i = 1; i <= n; ++i) val[i] = read();
depth[1] = 1;
dfs(1);
size = pow(ncnt, 2.0 / 3.0);
bnum = ceil((double)ncnt / size);
for(int i = 1; i <= bnum; ++i)
for(int j = size * (i - 1) + 1; j <= i * size; ++j) belong[j] = i;
for(int i = 1; i <= Q; ++i) {
int opt = read(), a = read(), b = read();
if(opt) {
int lca = getlca(a, b);
q[++qcnt].t = ccnt;
q[qcnt].id = qcnt;
if(fir[a] > fir[b]) swap(a, b);
if(a == lca) q[qcnt].l = fir[a], q[qcnt].r = fir[b];
else q[qcnt].l = la[a], q[qcnt].r = fir[b], q[qcnt].lca = lca;
}
else {
ch[++ccnt].pos = a;
ch[ccnt].val = b;
}
}
sort(q + 1, q + qcnt + 1, cmp);
for(int i = 1; i <= qcnt; ++i) {
int ql = q[i].l, qr = q[i].r, qt = q[i].t, qlca = q[i].lca;
while(l < ql) work(aa[l++]);
while(l > ql) work(aa[--l]);
while(r < qr) work(aa[++r]);
while(r > qr) work(aa[r--]);
while(t < qt) modify(++t);
while(t > qt) modify(t--);
if(qlca) work(qlca);
ans[q[i].id] = now;
if(qlca) work(qlca);
}
for(int i = 1; i <= qcnt; ++i) printf("%lld\n", ans[i]);
return 0;
}

【Luogu P4074】[WC2013]糖果公园(树上带修改莫队)的更多相关文章

  1. LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)

    传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...

  2. [WC2013][luogu4074] 糖果公园 [树上带修改莫队]

    题面: 传送门 思路: 一道实现起来细节比较恶心的题目 但是其实就是一个裸的树上带修改莫队 好像树上莫队也出不了什么结合题目,不像序列莫队天天结合AC自动机.后缀数组...... 莫队学习请戳这里:莫 ...

  3. luogu4074 [WC2013]糖果公园(树上带修莫队)

    link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...

  4. 【BZOJ-3052】糖果公园 树上带修莫队算法

    3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MBSubmit: 883  Solved: 419[Submit][Status] ...

  5. [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)

    BZOJ3585,BZOJ2120,BZOJ3757三合一. 对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队. 这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度. 剩下 ...

  6. P4074 [WC2013]糖果公园 树上莫队带修改

    题目链接 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 nn 个游览点构 ...

  7. BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)

    题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...

  8. 【Luogu】P1903数颜色(带修改莫队)

    题目链接 带修改莫队模板. 加一个变量记录现在是第几次修改,看看当前枚举的询问是第几次修改,改少了就改过去,改多了就改回来. 话说我栈用成队列了能过样例?!!!! 从此深信一句话:样例是出题人精心设计 ...

  9. luogu P4074 [WC2013]糖果公园

    传送门 这种题显然要用树上莫队 何为树上莫队?就是在树上跑莫队算法就是先把树分块,然后把询问离线,按照左端点所在块为第一关键字,右端点所在块为第二关键字,时间戳(如果有修改操作)为第三关键字排序,然后 ...

随机推荐

  1. 【MEVN架构】mongodb+ express + vue + nodejs 搭建后台

    前端技术栈:vue2 + vuex + vue-router + webpack + ES6/7 + less + element-ui 服务端技术栈:nodejs + express + mongo ...

  2. JS 01 变量_数据类型_分支循环_数组

    点击直通车↓↓↓ 数据类型及数据类型的手动转换 数组 一.概念 JavaScript(JS)是一种基于对象和事件驱动.且可以与HTML标记语言混合使用的脚本语言,其编写的程序可以直接在浏览器中解释执 ...

  3. SAP查询TABLE对应的文本表

    SAP 取数时,通常配置项,需要取对应的文本描述,一般在配置表后加个T,就可以找到描述对应的表名. 但有时也有不符合这个规则的,例如生产订单类型数据表 T003O. 表名加T后并不存T003OT. 这 ...

  4. 20155202张旭 Exp7 网络欺诈技术防范

    20155202张旭 Exp7 网络欺诈技术防范 基础问题回答 通常在什么场景下容易受到DNS spoof攻击? 在同一局域网下比较容易受到DNS spoof攻击,攻击者可以冒充域名服务器,来发送伪造 ...

  5. 20155204《网络对抗》Exp 6 信息搜集与漏洞扫描

    20155204<网络对抗>Exp 6 信息搜集与漏洞扫描 一.实验后回答问题 1.哪些组织负责DNS,IP的管理. 互联网名称与数字地址分配机构,简称ICANN机构,决定了域名和IP地址 ...

  6. 2017-2018-2 20155233『网络对抗技术』Exp6:信息收集与漏洞扫描

    通过DNS和IP挖掘目标网站的信息 whois查询:用来进行域名注册信息查询,以得到3R注册信息,包括注册人的名字.组织.城市等信息.(进行whois查询时去掉www等前缀,因为注册域名时通常会注册一 ...

  7. 20155239吕宇轩《网络对抗》Exp3 免杀原理与实践

    20155239吕宇轩<网络对抗>Exp3 免杀原理与实践 实验过程 Kali使用上次实验msfvenom产生后门的可执行文件,上传到老师提供的网址http://www.virscan.o ...

  8. 20155321 《网络攻防》 Exp3 免杀原理与实践

    20155321 <网络攻防> Exp3 免杀原理与实践 基础问题回答 杀软是如何检测出恶意代码的? 根据实验指导书,杀软有两个方法可以检测出恶意代码.第一种是基于特征码,即先对流行代码特 ...

  9. ILSVRC2016目标检测任务回顾——视频目标检测(VID)

    转自知乎<深度学习大讲堂> 雷锋网(公众号:雷锋网)按:本文作者王斌,中科院计算所前瞻研究实验室跨媒体计算组博士生,导师张勇东研究员.2016年在唐胜副研究员的带领下,作为计算所MCG-I ...

  10. Java 多线程之 Thread 类 和 Runnable 接口初步使用

    目录 Thread 类 Thread之定义线程类 Thread之开启线程 Runnable 接口 Runnable 之定义线程类 Runnable 之开启线程 @ Thread 类 Thread 类是 ...