问题描述

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 最好的朋友,你决定帮他一把。

思路

树上莫队板子 qwq

#include <bits/stdc++.h>
#define ri register
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
int n,m,Q,cntq,cntc,Time,block,mark[maxn],dep[maxn],cnt[maxn],father[maxn][20],dfn[maxn],v[maxn],w[maxn],x[maxn],edgecnt,first[maxn];
ll tot,ans[maxn];
struct edge {
int to,next;
}eg[maxn];
inline void addedge(ri int u,ri int v){
eg[++edgecnt] = (edge){v,first[u]}; first[u] = edgecnt;
eg[++edgecnt] = (edge){u,first[v]}; first[v] = edgecnt;
}
inline int read() {
char ch = getchar();
ri int x = 0, f = 1;
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
void write(ll x) {
ri ll y = 10,len = 1;
while (y <= x) { y *= 10; len++; }
while (len--) { y /= 10; putchar(x/y+48); x %= y; }
}
struct Query {
int l,r,num,c;
inline bool operator < (Query cmp) const {
if (dfn[l]/block != dfn[cmp.l]/block) return dfn[l]/block < dfn[cmp.l]/block;
if (dfn[r]/block != dfn[cmp.r]/block) return dfn[r]/block < dfn[cmp.r]/block;
return c < cmp.c;
}
}q[maxn];
struct Change {
int pos,to;
}c[maxn];
inline void dfs(ri int now,ri int fa) {
father[now][0] = fa;
dfn[now] = ++Time;
dep[now] = dep[fa]+1;
ri size_t i;
for (i = first[now];~i;i = eg[i].next)
if (eg[i].to != fa) dfs(eg[i].to,now);
}
inline void init() {
ri int i,j;
for (j = 1;(1<<j) <= n;j++)
for (i = 1;i <= n;i++)
father[i][j] = father[father[i][j-1]][j-1];
}
inline int lca(ri int a,ri int b) {
if (dep[a] < dep[b]) swap(a,b);
ri int i,j; for (i = 0;(1<<i) <= dep[a];i++); i--;
for (j = i;j >= 0;j--)
if (dep[a]-(1<<j) >= dep[b]) a = father[a][j];
if (a == b) return a;
for (j = i;j >= 0;j--)
if (father[a][j] != father[b][j]) a = father[a][j],b = father[b][j];
return father[a][0];
}
inline void reverse(ri int i) {
if (mark[i]) { mark[i] ^= 1; tot -= (long long)w[cnt[x[i]]--]*(long long)v[x[i]]; }
else { mark[i] ^= 1; tot += (long long)w[++cnt[x[i]]]*(long long)v[x[i]]; }
}
inline void change(ri int i) {
if (!mark[c[i].pos]) swap(c[i].to,x[c[i].pos]);
else {
reverse(c[i].pos);
swap(c[i].to,x[c[i].pos]);
reverse(c[i].pos);
}
}
int main() {
memset(first,-1,sizeof(first));
n = read(),m = read(),Q = read();
block = pow(n,2.0/3)*0.5;
ri int i,t,X,y;
for (i = 1;i <= m;i++) v[i] = read();
for (i = 1;i <= n;i++) w[i] = read();
for (i = 1;i < n;i++) X = read(),y = read(),addedge(X,y);
for (i = 1;i <= n;i++) x[i] = read();
dfs(1,0);
init();
for (i = 1;i <= Q;i++) {
t = read(),X = read(),y = read();
if (!t) c[++cntc].pos = X,c[cntc].to = y;
else q[++cntq].l = X,q[cntq].r = y,q[cntq].num = cntq,q[cntq].c = cntc;
}
sort(q+1,q+cntq+1);
if (dfn[q[1].l] > dfn[q[1].r]) swap(q[1].l,q[1].r);
ri ll LCA = lca(q[1].l,q[1].r),curl = q[1].l,curr = q[1].r,curc = 0,l = curl,r = curr;
while (l != LCA) reverse(l),l = father[l][0];
while (r != LCA) reverse(r),r = father[r][0];
while (curc < q[1].c) change(++curc);
reverse(LCA); ans[q[1].num] = tot; reverse(LCA);
for (i = 2;i <= cntq;i++) {
if (dfn[q[i].l] > dfn[q[i].r]) swap(q[i].l,q[i].r);
LCA = lca(q[i].r,curr),l = curr,r = q[i].r;
while (l != LCA) reverse(l),l = father[l][0];
while (r != LCA) reverse(r),r = father[r][0];
LCA = lca(q[i].l,curl),l = curl,r = q[i].l;
while (l != LCA) reverse(l),l = father[l][0];
while (r != LCA) reverse(r),r = father[r][0];
while (curc < q[i].c) change(++curc);
while (curc > q[i].c) change(curc--);
LCA = lca(q[i].l,q[i].r);
reverse(LCA); ans[q[i].num] = tot; reverse(LCA);
curl = q[i].l,curr = q[i].r;
}
for (i = 1;i <= cntq;i++) write(ans[i]),putchar('\n');
return 0;
}

【WC2013】 糖果公园 - 树上莫队的更多相关文章

  1. 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 ...

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

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

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

    题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...

  4. BZOJ 3052: [wc2013]糖果公园 | 树上莫队

    题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...

  5. 【WC2013】糖果公园 [树上莫队]

    题意: 一棵树,修改一个点的颜色,询问两点路径上每种颜色的权值$val[c]$*出现次数的权值$cou[w[c]]$的和 sro VFK 树上莫队 按照王室联邦的方法分块,块的大小直径个数有保证,并不 ...

  6. 洛谷P4074 [WC2013]糖果公园(莫队)

    传送门 总算会树形莫队了…… 上次听说树形莫队是给树分块,实在看不懂.然后用括号序列的方法做总算能弄明白了 先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下 拿 ...

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

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

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

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

  9. 【BZOJ3052】【UOJ#58】【WC2013】糖果公园(树上莫队)

    [BZOJ3052][UOJ#58][WC2013]糖果公园(树上莫队) 题面 UOJ 洛谷 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引 ...

随机推荐

  1. scratch编程我的世界3D史蒂夫

    这个程序我们只能制作出一个3D模型而已,并不是真正的我的世界整个游戏: 效果很炫酷吧!现在我们就来看看是怎样编程的吧! 首先,这个模型是有无数个平面克隆体摞在一起,旋转后会产生一种立体的错觉,是不是有 ...

  2. 设计模式:fly weight模式

    目的:通过共享实例的方式来避免重复的对象被new出来,节约系统资源 别名:享元模式 例子: class Char //共享的类,轻量级 { char c; public: Char(char c) { ...

  3. vue使用elementUI form表单label样式修改

    更多关于修改ElementUI样式的方法,可以参考这篇文章 1.删除style标签中的 scoped 属性 <style lang="lang" scoped> ... ...

  4. 检查string是否有重复尝试用map

    链接: 题意:输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文本的另外一个单词.在判断是否满足条件时,字母不分大小写,但在输出时应保留输入的大小写,按字典序排列. 题解:先 ...

  5. JAXB XML生成CDATA类型的节点

    试了好久才找到一个解决办法,我是用的JAXB的,如果你们也是用JAXB那么可以直接借鉴此方法,别的方式你们自行测试吧 第一步:新增一个适配器类 package com.message.util; im ...

  6. 关于git的一些简单命令

    git简介 1 Git是什么? Git is a free and open source distributed version control system designed to handle ...

  7. state实例

    States是SaltStack中的配置语言,在日常进行配置管理时需要编写大量的States文件. 比如我们需要安装一个包,然后管理一个配置文件,最后保证某个服务正常运行. 这里就需要我们编写一些st ...

  8. 【Laravel】 常用的artisian命令

    全局篇 查看artisian命令 php artisan php artisan list 查看某个帮助命令 php artisan help make:model 查看laravel版本 php a ...

  9. functools函数中的partial函数及wraps函数

    ''' partial引用函数,并增加形参 ''' import functools def show_arg(*args,**kwargs): print("args",args ...

  10. PHP strpbrk() 函数

    实例 在字符串中搜索字符 "oe",并返回字符串中从指定字符第一次出现的位置开始的剩余部分: <?php高佣联盟 www.cgewang.comecho strpbrk(&q ...