P4074 [WC2013]糖果公园 树上莫队带修改
Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩。
糖果公园的结构十分奇特,它由 nn 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 11 至 nn。有 nn – 11 条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。
糖果公园所发放的糖果种类非常丰富,总共有 mm 种,它们的编号依次为 11 至 mm。每一个糖果发放处都只发放某种特定的糖果,我们用 C_iCi 来表示 ii 号游览点的糖果。
来到公园里游玩的游客都不喜欢走回头路,他们总是从某个特定的游览点出发前往另一个特定的游览点,并游览途中的景点,这条路线一定是唯一的。他们经过每个游览点,都可以品尝到一颗对应种类的糖果。
大家对不同类型糖果的喜爱程度都不尽相同。 根据游客们的反馈打分,我们得到了糖果的美味指数, 第 ii 种糖果的美味指数为 V_iVi。另外,如果一位游客反复地品尝同一种类的糖果,他肯定会觉得有一些腻。根据量化统计,我们得到了游客第 ii 次品尝某类糖果的新奇指数 W_iWi。如果一位游客第 ii 次品尝第 jj 种糖果,那么他的愉悦指数 HH 将会增加对应的美味指数与新奇指数的乘积,即 V_jVj×W_iWi。这位游客游览公园的愉悦指数最终将是这些乘积的和。
当然,公园中每个糖果发放点所发放的糖果种类不一定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 mm 种中的一种),这样的目的是能够让游客们总是感受到惊喜。
糖果公园的工作人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学不好的小 A 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。
输入格式
从文件 park.in 中读入数据。
第一行包含三个正整数 nn, mm, qq, 分别表示游览点个数、 糖果种类数和操作次数。
第二行包含 mm 个正整数 V_1V1, V_2V2, …, V_mVm。
第三行包含 nn 个正整数 W_1W1, W_2W2, …, W_nWn。
第四行到第 nn + 22 行,每行包含两个正整数 A_iAi, B_iBi,表示这两个游览点之间有路径可以直接到达。
第 nn + 33 行包含 nn 个正整数 C_1C1, C_2C2, …, C_nCn。
接下来 qq 行, 每行包含三个整数 TypeType, xx, yy,表示一次操作:
若 TypeType 为 00,则 11 ≤ xx ≤ nn, 11 ≤ yy ≤ mm,表示将编号为 xx 的游览点发放的糖果类型改为 yy;
若 TypeType 为 11,则 11 ≤ x, yx,y ≤ nn,表示对出发点为 xx,终止点为 yy 的路线询问愉悦指数。
输出格式
输出到文件 park.out 中。
按照输入的先后顺序,对于每个 TypeType 为 11 的操作输出一行,用一个正整数表示答案。
输入输出样例
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
84
131
27
84
题意:
给你n个节点,m种糖果,Q次询问
后面给出m个数,代表每种糖果的值vi
后面给n个数,表示某种糖果如果吃了i次,它的新奇指数Wi
后面n-1行,给出n-1条边
后面再给出n个值ci,表示每一个节点最初是哪种糖果
后面就是Q次询问。每次询问如果Type=0,那么就把把x这个位置糖果种类改成y。如果Type=1,那就输出[x,y]区间的所有愉悦数的和
愉悦数就是vi*wi
题解:
这就是树上莫队加普通带修改莫队
SP10707 COT2 - Count on a tree II 树上莫队
我们通过欧拉序就可以转换成一个普通莫队
然后我们知道带修改莫队就是加了一个记录当前的时间变量time,如果现在的时间小于当前询问区间值得时间,那我们就需要把一些Modify操作执行,然后才是正确的结果
for(ll i=1; i<=Q; ++i)
{
ll start = node[i].l, last = node[i].r, time = node[i].time, lca = node[i].lca;
while(l < start) work(ord[l++]);
while(l > start) work(ord[--l]);
while(r < last) work(ord[++r]);
while(r > last) work(ord[r--]);
while(t < time) modify(++t); //判断当前时间有没有遇到更新内容
while(t > time) modify(t--);
if(lca) work(lca);
ans[node[i].id] = now;
if(lca) work(lca);
}
对于修改操作,我们需要判断当前需要修改的位置有没有影响到现在这个区间的答案,如果影响到了执行
if(vis[que[x].pos]) //如果vis数组值为1,就表示这个位置的值为答案做了贡献
{ //,所以如果这个位置改变就会影响答案
work(que[x].pos);
swap(val[que[x].pos], que[x].val);
work(que[x].pos);
}
否则就修改一下这个位置的值就可以了
swap(val[que[x].pos], que[x].val);
代码:
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <cmath>
#include <stack>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+10;
const int INF = 0x3f3f3f3f;
const double PI = 3.1415926;
const long long N = 1000006;
const double eps = 1e-10;
typedef long long ll;
#define mem(A, B) memset(A, B, sizeof(A))
#define lson rt<<1 , L, mid
#define rson rt<<1|1 , mid + 1, R
#define ls rt<<1
#define rs rt<<1|1
#define SIS std::ios::sync_with_stdiget_mod_new(z-x)o(false), cin.tie(0), cout.tie(0)
#define pll pair<long long, long long>
#define lowbit(abcd) (abcd & (-abcd))
#define max(a, b) ((a > b) ? (a) : (b))
#define min(a, b) ((a < b) ? (a) : (b))
inline ll read() //读取整数
{
ll res = 0;
char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
return res;
}
ll arr[maxn],cnt[maxn],first[maxn],second[maxn],ans[maxn],belong[maxn];
ll cnte,vis[maxn],sizes,new_size,len,now,n,m,typ[maxn],que_len; //莫队相关
ll ord[maxn],val[maxn],head[maxn],depth[maxn],fa[maxn][30],nod_len;
//ord保存的是欧拉序
struct edge
{
ll to,next;
} e[maxn];
struct Node
{
ll l,r,lca,id,time;
} node[maxn];
struct query
{
ll pos,val;
} que[maxn];
ll cmp(Node a, Node 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.time < b.time );
}
void add_edge(ll x,ll y)
{
e[++cnte]=(edge)
{
y,head[x]
};
head[x]=cnte;
e[++cnte]=(edge)
{
x,head[y]
};
head[y]=cnte;
}
void dfs(ll x) //求欧拉序,顺便为求lca做准备
{
ord[++len]=x;
first[x]=len;
for(ll i=head[x]; i; i=e[i].next)
{
ll to=e[i].to;
if(to==fa[x][0]) continue;
depth[to]=depth[x]+1;
fa[to][0]=x;
for(ll j=1; (1<<j)<=depth[to]; ++j)
{
fa[to][j]=fa[fa[to][j-1]][j-1];
}
dfs(to);
}
ord[++len]=x;
second[x]=len;
}
ll get_lca(ll u,ll v) //使用倍增lca
{
if(depth[u] < depth[v])
swap(u, v);
for(ll i = 20; i + 1; --i)
if(depth[u] - (1 << i) >= depth[v])
u = fa[u][i];
if(u == v)
return u;
for(ll i = 20; i + 1; --i)
if(fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
return fa[u][0];
}
inline void add(ll pos)
{
now += 1ll * typ[val[pos]] * arr[++cnt[val[pos]]];
}
inline void del(ll pos)
{
now -= 1ll * typ[val[pos]] * arr[cnt[val[pos]]--];
}
inline void work(ll pos)
{
vis[pos] ? del(pos) : add(pos);
vis[pos] ^= 1;
}
void modify(ll x)
{
if(vis[que[x].pos]) //如果vis数组值为1,就表示这个位置的值为答案做了贡献
{ //,所以如果这个位置改变就会影响答案
work(que[x].pos);
swap(val[que[x].pos], que[x].val);
work(que[x].pos);
} //否则的话就不需要改变答案
else swap(val[que[x].pos], que[x].val);
}
int main()
{
//scanf("%d%d",&n,&m);
ll Q;
n=read();
m=read();
Q=read();
for(ll i=1;i<=m;++i)
{
typ[i]=read();
}
for(ll i=1; i<=n; ++i)
{
//scanf("%d",&val[i]);
arr[i]=read();
}
for(ll i=1; i<n; ++i)
{
ll x,y;
scanf("%lld%lld",&x,&y);
add_edge(x,y);
}
for(ll i=1;i<=n;++i)
val[i]=read();
depth[1]=1;
dfs(1);
sizes=pow(len, 2.0 / 3.0); //注意,这个分块才是最优
new_size=ceil((double)len/sizes);
for(ll i=1; i<=new_size; ++i)
{
for(ll j=(i-1)*sizes+1; j<=i*sizes; ++j)
{
belong[j]=i;
}
}
//printf("*****\n");
for(ll i=1; i<=Q; ++i) //处理两种操作
{
ll opt,x,y,z;
opt=read();
x=read();
y=read();
//scanf("%lld%lld",&x,&y);
if(opt)
{
z=get_lca(x,y);
node[++nod_len].time=que_len;
if(first[x]>first[y]) swap(x,y);
if(x==z)
{
node[nod_len].l=first[x];
node[nod_len].r=first[y];
}
else
{
node[nod_len].l=second[x];
node[nod_len].r=first[y];
node[nod_len].lca=z;
}
node[nod_len].id=nod_len;
}
else
{
que[++que_len].pos=x;
que[que_len].val=y;
}
}
//printf("**\n");
sort(node+1,node+1+nod_len,cmp);
ll l=1,r=0,t=0;
for(ll i=1; i<=Q; ++i)
{
ll start = node[i].l, last = node[i].r, time = node[i].time, lca = node[i].lca;
while(l < start) work(ord[l++]);
while(l > start) work(ord[--l]);
while(r < last) work(ord[++r]);
while(r > last) work(ord[r--]);
while(t < time) modify(++t); //判断当前时间有没有遇到更新内容
while(t > time) modify(t--);
if(lca) work(lca);
ans[node[i].id] = now;
if(lca) work(lca);
}
for(ll i=1; i<=nod_len; ++i)
printf("%lld\n",ans[i]);
return 0;
}
P4074 [WC2013]糖果公园 树上莫队带修改的更多相关文章
- BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)
题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...
- 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 ...
- 洛谷P4074 [WC2013]糖果公园(莫队)
传送门 总算会树形莫队了…… 上次听说树形莫队是给树分块,实在看不懂.然后用括号序列的方法做总算能弄明白了 先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下 拿 ...
- BZOJ 3052: [wc2013]糖果公园 | 树上莫队
题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...
- LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
- 【WC2013】 糖果公园 - 树上莫队
问题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩.糖果公园的结构十分奇特,它由 n 个游览点构成, ...
- 【WC2013】糖果公园 [树上莫队]
题意: 一棵树,修改一个点的颜色,询问两点路径上每种颜色的权值$val[c]$*出现次数的权值$cou[w[c]]$的和 sro VFK 树上莫队 按照王室联邦的方法分块,块的大小直径个数有保证,并不 ...
- 洛谷 P4074 [WC2013]糖果公园 解题报告
P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...
- [洛谷P4074][WC2013]糖果公园
题目大意:给一棵$n$个节点的树,每个点有一个值$C_i$,每次询问一条路径$x->y$,求$\sum\limits_{c}val_c\times \sum\limits_{i=1}^{cnt_ ...
随机推荐
- UnityToLaya小插件-找出空格并替换
unity导出的文件中经常会出现带有空格的节点或者文件夹 而这些空格在本地开发测试过程中不会出现,当这些带有空格路径的文件需要放到网络上时,就出现问题了 所以这里写了一个简单的查找并清理空格的插件, ...
- Azure Terraform(四)状态文件存储
一,引言 我们都知道在执行部署计划之后,当前目录中就产生了名叫 "" 的 Terraform 的状态文件,该文件中记录了已部署资源的状态.默认情况下,在执行部署计划后,Terraf ...
- 汇编学习笔记——DOS及DEBUG介绍
转自:https://www.shiyanlou.com/courses/running/332 一.课程简介 声明:该课程基于<汇编语言(第2版)>郑晓薇 编著,机械工业出版社.本节实验 ...
- MySQL全面瓦解20:可编程性之流程控制语句
背景 说到流程控制语句,我们在程序语法中用的比较多,比如C#的if..else...,while...,?: 等.同样的,在MySQL中,也有一些流程控制的语法,方便我们在写函数.存储过程的时候对逻辑 ...
- 【Android】编译报错 Annotation processors must be explicitly declared now 解决方案
问题 在网上下载一个demo,因为版本久远,里面添加了本地 Butter Knife 的jar包,在编译时报错 Annotation processors must be explicitly dec ...
- TCP半连接队列和全连接
概述 如上图所示, 在TCP三次握手中,服务器维护一个半连接队列(sync queue) 和一个全连接队列(accept queue). 当服务端接收到客户端第一次SYN握手请求时,将创建的req ...
- vscode远程开发安装
https://www.cnblogs.com/xiaoqi/p/vs-code-remote.html ============================= https://blog.csdn ...
- Linux下编译安装源码包软件 configure ,make, make install, make test/check, make clean 假目标
http://www.360doc7.net/wxarticlenew/541275971.html 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 ...
- WebServices 与 Web API 的区别
WebServices : WebServices 是可以通过 Internet 访问并通过 XML 编码规范其通信的任何服务. 客户通过发送请求(大部分是 XML消息)来召唤 WebServices ...
- jsaper子报表Subreport(父子报表互相传值)
有很多人都说Jasperreports不适合中国式复杂报表,实际上运用好父子报表可以解决大部分问题了.例如下面的表.每个学生的学科数目不固定,且每个学生后有相当于小计的平均分.有点复杂度的报表,可以使 ...