热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[UOJ]#58.【WC2013】糖果公园:树上动态修改莫队算法优化

Candyland的糖果公园以其独特的结构吸引了众多喜爱糖果的小朋友。公园内设有多个游览点,每个点不仅景色宜人,还提供免费的糖果。这些游览点通过复杂的路径连接,形成了一棵包含n个节点的树状结构。为了优化游客体验,公园管理团队采用了一种基于树上动态修改的莫队算法,有效提升了糖果发放和游玩项目的管理效率。

Candyland 有一座糖果公园,公园里不仅有美丽的风景、好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园玩。

糖果公园的结构十分奇特,它由 nn 个游览点构成,每个游览点都有一个糖果发放处,我们可以依次将游览点编号为 11 至 nn。有 n−1n−1 条双向道路连接着这些游览点,并且整个糖果公园都是连通的,即从任何一个游览点出发都可以通过这些道路到达公园里的所有其它游览点。

糖果公园所发放的糖果种类非常丰富,总共 mm 种,它们的编号依次为 11 至 mm。每一个糖果发放处都只发放某种特定的糖果,我们用 cici 来表示 ii 号游览点的糖果。

来到公园里游玩的游客都不喜欢走回头路,他们总是从某个特定的游览点出发前往另一个特定的游览点,并游览途中的景点,这条路线一定是唯一的。他们经过每个游览点,都可以品尝到一颗对应种类的糖果。

大家对不同类型的糖果的喜爱程度都不尽相同。根据游客们的反馈打分,我们得到了糖果的美味指数,第 ii 种糖果的美味指数为 vivi。另外,如果一位游客反复地品尝同一种类的糖果,他肯定会觉得有一些腻。根据量化统计,我们得到了游客第 ii 次品尝某类糖果的新奇指数 wiwi,如果一位游客第 ii 次品尝第 jj 种糖果,那么他的愉悦指数 HH 将会增加对应的美味指数与新奇指数的乘积,即 vjwivjwi。这位游客游览公园的愉悦指数最终将是这些乘积的和。

当然,公园中每个糖果发放点所发放的糖果种类不一定是一成不变的。有时,一些糖果点所发放的糖果种类可能会更改(也只会是 mm 种中的一种),这样的目的是能够让游客们总是感受到惊喜。

糖果公园的工作人员小 A 接到了一个任务,那就是根据公园最近的数据统计出每位游客游玩公园的愉悦指数。但数学不好的小 A 一看到密密麻麻的数字就觉得头晕,作为小 A 最好的朋友,你决定帮他一把。

输入格式
第一行包含三个正整数 n,m,qn,m,q,分别表示游览点个数、糖果种类数和操作次数。

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

第三行包含 nn 个正整数 w1,w2,…,wnw1,w2,…,wn。

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

第 n+3n+3 行包含 nn 个正整数 c1,c2,…,cnc1,c2,…,cn。

接下来 qq 行,每行包含三个整数 t,x,yt,x,y,表示一次操作:

若 tt 为 00,则 1≤x≤n1≤x≤n,1≤y≤m1≤y≤m,表示编号为 xx 的游览点发放的糖果类型改为 yy;

若 tt 为 11,则 1≤x,y≤n1≤x,y≤n,表示对出发点为 xx,终止点为 yy 的路线询问愉悦指数。

输出格式
按照输入的先后顺序,对于每个 tt 为 11 的操作输出一行,用一个正整数表示答案。

题解:

树上带修改莫队裸题。

代码:

#include
#include
#include
#include
#include
using namespace std;
#define LL long long
const int maxn=100010;
struct Edge{int y,next;}e[maxn*2];
int last[maxn],len=0;
void ins(int x,int y)
{
int t=++len;
e[t].y=y;e[t].next=last[x];last[x]=t;
}
int dep[maxn],fa[maxn][20];
int sta[maxn],top=0,bl[maxn],MX,cnt=0;
int n,m,a[maxn],c[maxn],block[320],l[320],r[320],vis[maxn];
LL v[maxn],w[maxn],Ans=0,ans[maxn];
void dfs(int x)
{
dep[x]=dep[fa[x][0]]+1;
for(int i=1;(1<1]][i-1];
int now=top;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa[x][0])continue;
fa[y][0]=x;dfs(y);
if(top-now>MX)
{
cnt++;
while(top>now)bl[sta[top--]]=cnt;
}
}
sta[++top]=x;
if(x==1)
{
cnt++;
while(top)bl[sta[top--]]=cnt;
}
}
int LCA(int x,int y)
{
if(dep[x]//x jump
for(int i=18;i>=0;i--)
if((1< if(x==y)return x;
for(int i=18;i>=0;i--)
if(dep[x]>=(1< return fa[x][0];
}
void add(int x){Ans+=w[++c[a[x]]]*v[a[x]];}
void del(int x){Ans-=w[c[a[x]]--]*v[a[x]];}
void change(int x,int y)
{
if(vis[x])del(x),a[x]=y,add(x);
else a[x]=y;
}
void rev(int x)
{
if(vis[x])vis[x]=0,del(x);
else vis[x]=1,add(x);
}
struct Modify{int x,y,pre;}A[maxn];
struct Query{int x,y,time,id;}B[maxn];
bool cmp(Query a,Query b)
{
if(bl[a.x]!=bl[b.x])return bl[a.x] if(bl[a.y]!=bl[b.y])return bl[a.y] return a.time}
int la=0,lb=0,yl[maxn];
int main()
{
int q;
scanf("%d%d%d",&n,&m,&q);
MX=(int)pow(1.0*n*n,1.0/3);
for(int i=1;i<=m;i++)scanf("%lld",&v[i]);
for(int i=1;i<=n;i++)scanf("%lld",&w[i]);
for(int i=1;i {
int u,v;
scanf("%d%d",&u,&v);
ins(u,v);ins(v,u);
}
for(int i=1;i<=n;i++)scanf("%d",&a[i]),yl[i]=a[i];
dfs(1);
for(int i=1;i<=q;i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==0)
{
A[++la].x=x;A[la].y=y;
A[la].pre=a[x];
a[x]=y;
}
else
{
B[++lb].x=x;B[lb].y=y;
B[lb].time=la;B[lb].id=lb;
}
}
sort(B+1,B+1+lb,cmp);
for(int i=1;i<=n;i++)a[i]=yl[i];
int L=1,R=1;B[0].time=0;
for(int i=1;i<=lb;i++)
{
int l1=LCA(B[i].x,L);
int l2=LCA(B[i].y,R);
for(int x=L;x!=l1;x=fa[x][0])rev(x);
for(int x=B[i].x;x!=l1;x=fa[x][0])rev(x);
for(int x=R;x!=l2;x=fa[x][0])rev(x);
for(int x=B[i].y;x!=l2;x=fa[x][0])rev(x);
L=B[i].x;R=B[i].y;
int l=LCA(L,R);
rev(l);
for(int j=B[i-1].time+1;j<=B[i].time;j++)change(A[j].x,A[j].y);
for(int j=B[i-1].time;j>B[i].time;j--)change(A[j].x,A[j].pre);
ans[B[i].id]=Ans;
rev(l);
}
for(int i=1;i<=lb;i++)
printf("%lld\n",ans[i]);
}

推荐阅读
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 深入解析JVM垃圾收集器
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
author-avatar
尹一2502904223
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有