http://uoj.ac/problem/58

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]糖果公园——题解的更多相关文章

  1. 【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队

    [BZOJ3052][wc2013]糖果公园 Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 ...

  2. ●UOJ58 [WC2013]糖果公园

    题链: http://uoj.ac/problem/58题解: 树上带修莫队. 每个块的大小为$n^{\frac{2}{3}}$,在dfs时,把点集分为若干块. 然后类似序列带修莫队,三个关键字:be ...

  3. 【bzoj3052】[wc2013]糖果公园 带修改树上莫队

    题目描述 给出一棵n个点的树,每个点有一个点权,点权范围为1~m.支持两种操作:(1)修改一个点的点权 (2)对于一条路径,求$\sum\limits_{i=1}^m\sum\limits_{j=1} ...

  4. BZOJ3052:[WC2013]糖果公园

    浅谈莫队:https://www.cnblogs.com/AKMer/p/10374756.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...

  5. 【BZOJ3052&UOJ58】糖果公园(树上带修莫队)

    题意:给定一个n个点的树,每个结点上有一种颜色c[i] 定义一条简单路径的偷税指数为simga (sigma w[i](i=0..a[j]))*v[j](j=0..m),其中a[i]为第i种颜色在路径 ...

  6. [BZOJ3052][UOJ#58][WC2013]糖果公园

    [BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...

  7. bzoj 3052: [wc2013]糖果公园 带修改莫队

    3052: [wc2013]糖果公园 Time Limit: 250 Sec  Memory Limit: 512 MBSubmit: 506  Solved: 189[Submit][Status] ...

  8. 洛谷 P4074 [WC2013]糖果公园 解题报告

    P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...

  9. AC日记——[WC2013]糖果公园 cogs 1817

    [WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...

随机推荐

  1. L010 linux命令及基础手把手实战总结

    一转眼都快两周没更新了,最近实在太忙了,这两周的时间断断续续的把L010学完了,短短的15节课,确是把前10节的课程全部的运用一遍,从笔记到整理,再到重新理解,最后发布到微博,也确实提升了一些综合性能 ...

  2. VIN码识别,车架号识别,OCR扫描工具

    近年二手车交易市场火爆,对二手车估值需要了详细解二手车的历史状况,车架号(VIN码)是车辆唯一的身份标识,也是了解二手车车况的入口,车商和二手车平台会频繁的进行车况查询,VIN码扫描识别技术给车辆估值 ...

  3. word record 4

    word record 4 pledge p le g vt. 保证,许诺 snowflake falke->n. 小薄片:火花 deputy de piu ti n. 代理人,代表 etch ...

  4. C++11 type_traits 之is_same源码分析

    请看源码: template<typename _Tp, _Tp __v> struct integral_constant { static const _Tp value = __v; ...

  5. Java开发工程师(Web方向) - 03.数据库开发 - 第3章.SQL注入与防范

    第3章--SQL注入与防范 SQL注入与防范 经常遇到的问题:数据安全问题,尤其是sql注入导致的数据库的安全漏洞 国内著名漏洞曝光平台:WooYun.org 数据库泄露的风险:用户信息.交易信息的泄 ...

  6. Java开发工程师(Web方向) - 01.Java Web开发入门 - 第3章.Tomcat

    第3章--Tomcat Tomcat安装与运行 Tomcat:目前最常用的基于java的web应用服务器 本课程中所有的Java代码最终都需要部署到Tomcat中运行 Tomcat的配置文件是XML的 ...

  7. (python)leetcode刷题笔记 01 TWO SUM

    1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a ...

  8. IMPI Python集群运行报错:

    Intel MPI环境利用hostfile多主机运行下报错 HYDU_process_mfile_token (../../utils/args/args.c:523): token slots no ...

  9. Elasticsearch 相同内容文档,不同score(评分)的奇怪问题

    原文:http://stackoverflow.com/questions/14580752/elasticsearch-gives-different-scores-for-same-documen ...

  10. 使用Response.Write实现在页面的生命周期中前后台的交互

    Response.Write()方法非常的常见,也很普通,就是向http output中输出一string.其输出的内容位于页面的最顶端,常用来实现显示一些页面消息框等逻辑. 一般来说,在页面的整个生 ...