[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. 动态栅格(DEM)图层实现服务端渲染

    PS:此处动态图层指,图层文件都放在经过注册的文件目录里,可以通过文件名动态加载图层 动态加载的矢量图层,可以实现客户端和服务端的定制渲染,但栅格一般是不能再渲染的,以下介绍可行的方法 建立一个很简单 ...

  2. RxJava的map方法与flatMap方法

    简单讲,map和flatMap都是来完成Observable构造的数据到Observer接收数据的一个转换,这么说有点绕

  3. DMA简介

    直接存储器访问 直接存储器访问(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术.它可以让外设可以独立地直接读写系统存储器,而不需绕道中央处理器(CPU),DMA是一 ...

  4. C# string日期格式

    百分数格式应该用“p”这个参数. 格式 原始 数据 结 果 "{0:P}" 0.40 40% 数字 {0:N2} 12.36  数字 {0:N0} 13  货币 {0:c2} $1 ...

  5. (转)使用JDK中的Proxy技术实现AOP功能

    http://blog.csdn.net/yerenyuan_pku/article/details/52863780 AOP技术在企业开发中或多或少都会用到,但用的最多的大概就是做权限系统时,在做权 ...

  6. MySQL系列(三)--数据库结构优化

    良好的数据库逻辑设计和物理设计是数据库高性能的基础,所以对于数据库结构优化是很有必要的 数据库结构优化目的: 1.减少数据的冗余 2.尽量避免在数据插入.删除和更新异常 例如:有一张设计不得当的学生选 ...

  7. Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/config/spring/applicationContext.xml]

    在搭建SpringMVC框架的时候遇到了这个问题 问题的原因: 就是没有找到applicatoincontext.xml这个文件, 因为idea自动生成的路径不正确 因此需要再web.xml里面, ( ...

  8. 洛谷 P3146 248 题解

    https://www.luogu.org/problemnew/show/P3146 区间dp,这次设计的状态和一般的有一定的差异. 这次我们定义$dp[i][j]$表示$[i,j]$的可以合并出来 ...

  9. POJ-1011(sticks,深搜)

    Description George took sticks of the same length and cut them randomly until all parts became at mo ...

  10. (16) Cloudflare pki公钥基础设施

    该工具组共有8个工具 1.cfssl 常用的可用指令: sign signs a certificate bundle build a certificate bundle genkey genera ...