BZOJ3052 & UOJ58:[WC2013]糖果公园——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3052
输入格式
输出格式
input
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
output
84
131
27
84
——————————————————————————————————————
这题对于一个刚学莫队的人来说……挺萌的。
首先先对树分块,具体请看我的前一篇博客王室联邦我们就可以知道,假设我们要分块,我们设预期分块大小为s,则所有块的大小可为[s,3s]。
按照这种分块方法分块即可,注意为了我们算法的速度,分块大小s=n的2/3次方,证明可看小兔大佬的博客中单点修改莫队。
(dfs同时预处理LCA所需要的几个数据,以后会用)
在那之后按照莫队的思路为询问排序,然后开始我们正式的算法。
(排序时0号点的l和r都设成1(看到下面的操作之后就会知道这样做干什么了))
这里说一下个别几个数组的含义。
1.sta[i]:i是否在当前路径上,是为1.
2.last[i]:第i个操作为修改时,修改前的颜色。
3.cc[i]:最终i点的颜色。
4.col[i]:当前操作时i点的颜色。
再说一个函数rev(i)表示将i这个点在我们的路径上被添加/删除。
剩下的应该都能看得懂,我就不说什么了。
首先按照排序后顺序扫询问,我们得到了我们当前的询问和前一个询问。
那么首先我们需要将前一个询问的id和后一个询问的id中间的修改操作修改了。
然后就是最神奇的操作了,solve操作的证明详见vfk的博客。
(当然你也可以通过画图肉眼观察法证明,以下简述solve内部操作)
我们把当前的左询问节点l和之前的左询问节点l0之间的最短路取反。(当然同时对右节点也是一样)
然后取反左右询问节点的LCA,再更新cur,在取反LCA,这样我们就得到了这个询问的答案了。
#include<cstdio>
#include<stack>
#include<cctype>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=;
const int INF=;
inline ll read(){
ll X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to;
int nxt;
}edge[N*];
struct qu{
int id,l,r,bl,br;
}qry[N];
int n,m,Q,q,s,cnt,head[N];
int top,idx,stk[N],blk[N];
int anc[N][],dep[N];
int v[N],cc[N],col[N],sum[N];
int a[N],b[N],op[N],last[N];
ll cur,ans[N],w[N];
bool sta[N];
inline void add(int u,int v){
cnt++;
edge[cnt].to=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
return;
}
bool cmp(qu d,qu e){
if(d.bl!=e.bl)return d.bl<e.bl;
if(d.br!=e.br)return d.br<e.br;
return d.id<e.id;
}
void dfs(int u){
int st=top;
dep[u]=dep[anc[u][]]+;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==anc[u][])continue;
anc[v][]=u;
dfs(v);
if(top-st>=s){
idx++;
while(top>st)blk[stk[top--]]=idx;
}
}
stk[++top]=u;
return;
}
int LCA(int i,int j){
if(dep[i]<dep[j])swap(i,j);
for(int k=;k>=;k--){
if(dep[anc[i][k]]>=dep[j])i=anc[i][k];
}
if(i==j)return i;
for(int k=;k>=;k--){
if(anc[i][k]!=anc[j][k])i=anc[i][k],j=anc[j][k];
}
return anc[i][];
}
void init(){
n=read();m=read();Q=read();s=pow(n,2.0/3.0);
for(int i=;i<=m;i++)v[i]=read();
for(int i=;i<=n;i++)w[i]=read()+w[i-];
for(int i=;i<n;i++){
int u=read(),v=read();
add(u,v);add(v,u);
}
for(int i=;i<=n;i++)cc[i]=col[i]=read();
dfs();
while(top)blk[stk[top--]]=idx;
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
anc[i][j]=anc[anc[i][j-]][j-];
}
}
return;
}
inline void rev(int x){
cur-=w[sum[col[x]]]*v[col[x]];
sta[x]?sum[col[x]]--:sum[col[x]]++;
sta[x]=!sta[x];
cur+=w[sum[col[x]]]*v[col[x]];
return;
}
inline void solve(int x,int y){
int l=LCA(x,y);
while(x!=l)rev(x),x=anc[x][];
while(y!=l)rev(y),y=anc[y][];
return;
}
inline void modify(int x,int y){
if(!sta[x]){
col[x]=y;
return;
}
rev(x);
col[x]=y;
rev(x);
return;
}
inline void upt(int tarT,int curT){
while(curT<tarT){
curT++;
if(!op[curT])modify(a[curT],b[curT]);
}
while(curT>tarT){
if(!op[curT])modify(a[curT],last[curT]);
curT--;
}
return;
}
int main(){
init();
for(int i=;i<=Q;i++){
op[i]=read(),a[i]=read(),b[i]=read();
if(op[i]){
qry[++q].id=i;
if(blk[a[i]]>blk[b[i]])swap(a[i],b[i]);
qry[q].l=a[i];qry[q].r=b[i];
qry[q].bl=blk[a[i]];qry[q].br=blk[b[i]];
}else last[i]=cc[a[i]],cc[a[i]]=b[i];
}
sort(qry+,qry+q+,cmp);
qry[].l=qry[].r=;
for(int i=;i<=q;i++){
upt(qry[i].id,qry[i-].id);
solve(qry[i].l,qry[i-].l);solve(qry[i].r,qry[i-].r);
int l=LCA(qry[i].l,qry[i].r);
rev(l);
ans[qry[i].id]=cur;
rev(l);
}
for(int i=;i<=Q;i++){
if(op[i])printf("%lld\n",ans[i]);
}
return ;
}
BZOJ3052 & UOJ58:[WC2013]糖果公园——题解的更多相关文章
- 【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队
[BZOJ3052][wc2013]糖果公园 Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 ...
- ●UOJ58 [WC2013]糖果公园
题链: http://uoj.ac/problem/58题解: 树上带修莫队. 每个块的大小为$n^{\frac{2}{3}}$,在dfs时,把点集分为若干块. 然后类似序列带修莫队,三个关键字:be ...
- 【bzoj3052】[wc2013]糖果公园 带修改树上莫队
题目描述 给出一棵n个点的树,每个点有一个点权,点权范围为1~m.支持两种操作:(1)修改一个点的点权 (2)对于一条路径,求$\sum\limits_{i=1}^m\sum\limits_{j=1} ...
- BZOJ3052:[WC2013]糖果公园
浅谈莫队:https://www.cnblogs.com/AKMer/p/10374756.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...
- 【BZOJ3052&UOJ58】糖果公园(树上带修莫队)
题意:给定一个n个点的树,每个结点上有一种颜色c[i] 定义一条简单路径的偷税指数为simga (sigma w[i](i=0..a[j]))*v[j](j=0..m),其中a[i]为第i种颜色在路径 ...
- [BZOJ3052][UOJ#58][WC2013]糖果公园
[BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...
- bzoj 3052: [wc2013]糖果公园 带修改莫队
3052: [wc2013]糖果公园 Time Limit: 250 Sec Memory Limit: 512 MBSubmit: 506 Solved: 189[Submit][Status] ...
- 洛谷 P4074 [WC2013]糖果公园 解题报告
P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...
- AC日记——[WC2013]糖果公园 cogs 1817
[WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...
随机推荐
- SpringBoot学习:整合shiro(验证码功能和登录次数限制功能)
项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)验证码 首先login.jsp里增加了获取验证码图片的标签: <body s ...
- 使用vs code写php及调试
原文来自:http://www.cnblogs.com/CLR010/p/5276077.html 首页先改下php.ini 一般是在最底部,有就修改没有就加上去下面的配置: xdebug.remot ...
- hive自定义函数——hive streaming
Hadoop Streaming提供了一个便于进行MapReduce编程的工具包,使用它可以基于一些可执行命令.脚本语言或其他编程语言来实现Mapper和 Reducer,Streaming方式是基于 ...
- CRL2.1更新
增加没有主键ID的抽象类,使能自义主键字段实现MODEL抽象类定义结构为 /// <summary> /// 基类,不包含任何字段 /// 如果有自定义主键名对象,请继承此类型 /// & ...
- oradebug 的学习 一
说明 oradebug主要是给oracle支持人员使用的,尽管很早便有,但oracle官网很少有记载.他是个sql*plus命令行工具,有sysdba的权限就可以登入,无需特别设置.他可以被用 ...
- vim程序员加强功能
1.折叠 1.1折叠的方式有六种 manual:以标准的vim结构定义折叠跨越的范围,类似移动命令 indent:折叠与折叠的层次,对应于文本的缩排与 ...
- Selenium自动化测试第一天(下)
如有任何学习问题,可以添加作者微信:lockingfree 目录 Selenium自动化测试基础 Selenium自动化测试第一天(上) Selenium自动化测试第一天(下) Selenium自动化 ...
- Siki_Unity_2-1_API常用方法和类详细讲解(上)
Unity 2-1 API常用方法和类详细讲解(上) 任务1&2:课程前言.学习方法 && 开发环境.查API文档 API: Application Programming I ...
- jmeter链接数据库问题汇总
1.最新驱动下载: 驱动版本与mysql服务不兼容也是会报错的 下载地址:https://dev.mysql.com/downloads/connector/j/ 打开页面一直拉到页面底部,此处选择P ...
- jetbrains系列激活
没钱,只能DB了. 为了避免某些个人私自搭建服务器,以及自己搭建激活服务器,因此,决定使用破解包~~~. 注意:只要破解,就要屏蔽官方激活服务器:0.0.0.0 account.jetbrains.c ...