
正文
【BZOJ-3052】糖果公园 树上带修莫队算法
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
3052: [wc2013]糖果公园
Time Limit: 200 Sec Memory Limit: 512 MB
Submit: 883 Solved: 419
[Submit][Status][Discuss]
Description
Input
Output
Sample Input


Output
Sample Input


Sample Output84
131
27
84HINT

SourceSolution
131
27
84


SourceSolution
树上带修莫队
本质还是树上莫队,详情可以转 BZOJ-3757苹果树
但是这里需要修改,就需要一些特殊的地方
首先DFS对树分块,没什么区别,只不过这里分块可以分得大一些,跑得快
把一个询问看成一个三元组$(a,b,t)$,$t$是询问的时间,这样对询问排序的时候,就是三关键字
然后在处理询问的时候,暴力处理修改,不过处理要分情况,如果经过则先对结果进行修改再修改数值,否则直接修改即可
并不是很详细,还是直接看VFleaKing的讲解吧ORZ VFK
启发:
莫队算法不仅可以处理不带修,同样可以处理带修的问题 (似乎还可以处理强制在线的?奇怪的姿势??)
分块的技巧有很多,应该根据实际情况去选择适合的块的大小
树上莫队的大体思路都比较类似,实际实现起来也非常像,遇到类似的问题可以如此考虑
平常得多做一些难写难调的花式题,使得码力++多看看神犇们的解题报告似乎是个不错的事
Code#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100010
#define maxm 100010
#define maxq 100010
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,Q,fk,knum,rt[maxn];long long V[maxm],W[maxn],an[maxn],C[maxn],ans;
struct Edgenode{int to,next;}edge[maxn<<];
int head[maxn],cnt;
void add(int u,int v)
{cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v)
{add(u,v);add(v,u);}
int stack[maxn],top,dfsx,dfs[maxn],deep[maxn],father[maxn][];
int DFS(int now)
{
int size=;
dfs[now]=++dfsx;
for (int i=; i<=; i++)
if (deep[now]>=(<<i)) father[now][i]=father[father[now][i-]][i-];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=father[now][])
{
deep[edge[i].to]=deep[now]+;
father[edge[i].to][]=now;
size+=DFS(edge[i].to);
if (size>=fk)
{
knum++;
for (int j=; j<=size; j++) rt[stack[top--]]=knum;
size=;
}
}
stack[++top]=now;
return size+;
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=; i<=; i++)
if (dd&(<<i) && dd>=(<<i)) x=father[x][i];
for (int i=; i>=; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x; else return father[x][];
}
bool visit[maxn]; int num[maxn];
void Reverse(int x)
{
if (visit[x]) {visit[x]=; ans-=W[num[C[x]]]*V[C[x]]; num[C[x]]--;}
else {visit[x]=; num[C[x]]++; ans+=W[num[C[x]]]*V[C[x]];}
// printf("%d\n",ans);
}
void Change(int x,int y)
{
if (visit[x]) Reverse(x),C[x]=y,Reverse(x);
else C[x]=y;
}
void work(int x,int y)
{
while (x!=y)
if (deep[x]>deep[y]) Reverse(x),x=father[x][];
else Reverse(y),y=father[y][];
}
struct Asknode
{
int a,b,t,id;
bool operator < (const Asknode & A) const
{
if (rt[a]==rt[A.a] && rt[b]==rt[A.b]) return t<A.t;
else if (rt[a]==rt[A.a]) return rt[b]<rt[A.b];
return rt[a]<rt[A.a];
}
}q[maxq];int numq;
struct Changenode{int a,b,t,p;}ch[maxq];int numc,p[maxq];
int main()
{
n=read(),m=read(),Q=read(); fk=pow(n,2.0/)*0.5;
for (int i=; i<=m; i++) V[i]=read();
for (int i=; i<=n; i++) W[i]=read();
for (int u,v,i=; i<=n-; i++) u=read(),v=read(),insert(u,v);
for (int i=; i<=n; i++) C[i]=read();
for (int i=; i<=n; i++) p[i]=C[i]; DFS();
// puts("OK");
// for (int i=1; i<=n; i++) printf("%d %d %d %d\n",V[i],W[i],dfs[i],p[i]);
// for (int i=1; i<=n; i++) printf("%d ",rt[i]); puts("");
// puts("OK");
while (top) rt[stack[top--]]=knum; for (int i=; i<=Q; i++)
{
int opt=read(),a=read(),b=read();
if (opt) {if (dfs[a]>dfs[b]) swap(a,b); numq++;q[numq].a=a; q[numq].b=b; q[numq].t=numc; q[numq].id=numq;}
else {numc++;ch[numc].a=a;ch[numc].b=b;ch[numc].t=i;ch[numc].p=p[a]; p[a]=b;}
}
sort(q+,q+numq+);
//for (int i=1; i<=numq; i++) printf("%d %d %d %d\n",q[i].a,q[i].b,q[i].id,q[i].t);
for (int i=; i<=q[].t; i++) Change(ch[i].a,ch[i].b);
work(q[].a,q[].b);
int T=LCA(q[].a,q[].b);
Reverse(T); an[q[].id]=ans; Reverse(T);
for (int i=; i<=numq; i++)
{
for(int j=q[i-].t+; j<=q[i].t; j++) Change(ch[j].a,ch[j].b);
for(int j=q[i-].t; j>q[i].t; j--) Change(ch[j].a,ch[j].p);
work(q[i-].a,q[i].a); work(q[i-].b,q[i].b);
T=LCA(q[i].a,q[i].b); Reverse(T); an[q[i].id]=ans; Reverse(T);
}
for (int i=; i<=numq; i++) printf("%lld\n",an[i]);
return ;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100010
#define maxm 100010
#define maxq 100010
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,Q,fk,knum,rt[maxn];long long V[maxm],W[maxn],an[maxn],C[maxn],ans;
struct Edgenode{int to,next;}edge[maxn<<];
int head[maxn],cnt;
void add(int u,int v)
{cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v)
{add(u,v);add(v,u);}
int stack[maxn],top,dfsx,dfs[maxn],deep[maxn],father[maxn][];
int DFS(int now)
{
int size=;
dfs[now]=++dfsx;
for (int i=; i<=; i++)
if (deep[now]>=(<<i)) father[now][i]=father[father[now][i-]][i-];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=father[now][])
{
deep[edge[i].to]=deep[now]+;
father[edge[i].to][]=now;
size+=DFS(edge[i].to);
if (size>=fk)
{
knum++;
for (int j=; j<=size; j++) rt[stack[top--]]=knum;
size=;
}
}
stack[++top]=now;
return size+;
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=; i<=; i++)
if (dd&(<<i) && dd>=(<<i)) x=father[x][i];
for (int i=; i>=; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x; else return father[x][];
}
bool visit[maxn]; int num[maxn];
void Reverse(int x)
{
if (visit[x]) {visit[x]=; ans-=W[num[C[x]]]*V[C[x]]; num[C[x]]--;}
else {visit[x]=; num[C[x]]++; ans+=W[num[C[x]]]*V[C[x]];}
// printf("%d\n",ans);
}
void Change(int x,int y)
{
if (visit[x]) Reverse(x),C[x]=y,Reverse(x);
else C[x]=y;
}
void work(int x,int y)
{
while (x!=y)
if (deep[x]>deep[y]) Reverse(x),x=father[x][];
else Reverse(y),y=father[y][];
}
struct Asknode
{
int a,b,t,id;
bool operator < (const Asknode & A) const
{
if (rt[a]==rt[A.a] && rt[b]==rt[A.b]) return t<A.t;
else if (rt[a]==rt[A.a]) return rt[b]<rt[A.b];
return rt[a]<rt[A.a];
}
}q[maxq];int numq;
struct Changenode{int a,b,t,p;}ch[maxq];int numc,p[maxq];
int main()
{
n=read(),m=read(),Q=read(); fk=pow(n,2.0/)*0.5;
for (int i=; i<=m; i++) V[i]=read();
for (int i=; i<=n; i++) W[i]=read();
for (int u,v,i=; i<=n-; i++) u=read(),v=read(),insert(u,v);
for (int i=; i<=n; i++) C[i]=read();
for (int i=; i<=n; i++) p[i]=C[i]; DFS();
// puts("OK");
// for (int i=1; i<=n; i++) printf("%d %d %d %d\n",V[i],W[i],dfs[i],p[i]);
// for (int i=1; i<=n; i++) printf("%d ",rt[i]); puts("");
// puts("OK");
while (top) rt[stack[top--]]=knum; for (int i=; i<=Q; i++)
{
int opt=read(),a=read(),b=read();
if (opt) {if (dfs[a]>dfs[b]) swap(a,b); numq++;q[numq].a=a; q[numq].b=b; q[numq].t=numc; q[numq].id=numq;}
else {numc++;ch[numc].a=a;ch[numc].b=b;ch[numc].t=i;ch[numc].p=p[a]; p[a]=b;}
}
sort(q+,q+numq+);
//for (int i=1; i<=numq; i++) printf("%d %d %d %d\n",q[i].a,q[i].b,q[i].id,q[i].t);
for (int i=; i<=q[].t; i++) Change(ch[i].a,ch[i].b);
work(q[].a,q[].b);
int T=LCA(q[].a,q[].b);
Reverse(T); an[q[].id]=ans; Reverse(T);
for (int i=; i<=numq; i++)
{
for(int j=q[i-].t+; j<=q[i].t; j++) Change(ch[j].a,ch[j].b);
for(int j=q[i-].t; j>q[i].t; j--) Change(ch[j].a,ch[j].p);
work(q[i-].a,q[i].a); work(q[i-].b,q[i].b);
T=LCA(q[i].a,q[i].b); Reverse(T); an[q[i].id]=ans; Reverse(T);
}
for (int i=; i<=numq; i++) printf("%lld\n",an[i]);
return ;
}
看论文+写+调了一整个上午..1min30s跑完..成功卡住5人评测TAT'' 吐槽一下BZOJ评测机..UOJ上就跑了20s..
【BZOJ-3052】糖果公园 树上带修莫队算法的更多相关文章- LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
- luogu4074 [WC2013]糖果公园(树上带修莫队)
link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...
- [WC2013][luogu4074] 糖果公园 [树上带修改莫队]
题面: 传送门 思路: 一道实现起来细节比较恶心的题目 但是其实就是一个裸的树上带修改莫队 好像树上莫队也出不了什么结合题目,不像序列莫队天天结合AC自动机.后缀数组...... 莫队学习请戳这里:莫 ...
- BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
- BZOJ3052: [wc2013]糖果公园【树上带修莫队】
Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...
- BZOJ 4129 Haruna’s Breakfast ( 树上带修莫队 )
题面 求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述 分析 树上带修莫队板题,问题是怎么求最小的没出现过的权值. 因为只有nnn个点,所以没出现过的最小值一定在[0,n][0,n][0, ...
- bzoj4129 Haruna’s Breakfast 树上带修莫队+分块
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
- BZOJ 3052 树上带修莫队
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
- 【BZOJ-2453&;2120】维护队列&;数颜色 分块 + 带修莫队算法
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 653 Solved: 283[Submit][Status][Discuss] ...
随机推荐- .NET 响应式自动缩略图服务器
做互联网网站,总是会涉及到缩略图问题,之前一直是在上传图片时生成不同尺寸的缩略图,一直感觉又费力又不好管理,之后就写子 ThumbnailServer 用于部署一个图片服务器,在使用图片时才将图片转为 ...
- Unity与Android的相互交互
1.Unity调用Android. Unity块代码: using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.play ...
- PHP生成二维码【谷歌API+qrcode+圆角Logo】
方法一:谷歌二维码API 接口地址:https://chart.googleapis.com/chart 官方文档:https://developers.google.com/chart/infogr ...
- SpringMVC拦截器2(资源和权限管理)(作为补充说明)
SpringMVC拦截器(资源和权限管理) 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServle ...
- DNS-解析、劫持、污染
DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工 ...
- Get Files from Directory
http://www.csharp-examples.net/get-files-from-directory/ Get Files from Directory [C#] This example ...
- 最详细的 HTTPS 科普扫盲帖
为什么需要https HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号,密码, ...
- Linux系统从安装开始
已经很久很久没来得及写博客了,想想之前自己开始安装使用Linux系统的尝试,好像很简单!下面开始Linux系统的安装:这里推荐U盘安装 首先你必须下载一个U盘ISO镜像写入工具,本人使用USBWrit ...
- Linux记录-JMX监控Tomcat上传到falcon
1.登录测试服务器xxxxxx xxxxxx su root输入xxxx 2.先修改Tomcat的启动脚本,(linux下为catalina.sh),添加以下内容: CATALINA_OPTS=&qu ...
- 《Python数据可视化编程实战》
第一章:准备工作环境 WinPython-32bit-3.5.2.2Qt5.exe 1.1 设置matplotlib参数 配置模板以方便各项目共享 D:\Bin\WinPython-32bit-3.5 ...
传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...
link 题目大意:给一个树,树上每个点都有一种颜色,每个颜色都有一个收益 每次修改一个点上的颜色 或询问一条链上所有颜色第i次遇到颜色j可以获得w[i]*v[j]的价值,求链上价值和 题解:树上带修 ...
题面: 传送门 思路: 一道实现起来细节比较恶心的题目 但是其实就是一个裸的树上带修改莫队 好像树上莫队也出不了什么结合题目,不像序列莫队天天结合AC自动机.后缀数组...... 莫队学习请戳这里:莫 ...
题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...
Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT 思路 非常模板的树上带修莫队 真的 ...
题面 求树上某路径上最小的没出现过的权值,有单点修改 添加链接描述 分析 树上带修莫队板题,问题是怎么求最小的没出现过的权值. 因为只有nnn个点,所以没出现过的最小值一定在[0,n][0,n][0, ...
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4129 题解 考虑没有修改的序列上的版本应该怎么做: 弱化的题目应该是这样的: 给定一个序列,每 ...
思路: 就是把带修莫队移到了树上 块的大小开到(n^2/3)/2 比较好- 这是一个卡OJ好题 //By SiriusRen #include <cmath> #include <c ...
2453: 维护队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 653 Solved: 283[Submit][Status][Discuss] ...
- .NET 响应式自动缩略图服务器
做互联网网站,总是会涉及到缩略图问题,之前一直是在上传图片时生成不同尺寸的缩略图,一直感觉又费力又不好管理,之后就写子 ThumbnailServer 用于部署一个图片服务器,在使用图片时才将图片转为 ...
- Unity与Android的相互交互
1.Unity调用Android. Unity块代码: using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.play ...
- PHP生成二维码【谷歌API+qrcode+圆角Logo】
方法一:谷歌二维码API 接口地址:https://chart.googleapis.com/chart 官方文档:https://developers.google.com/chart/infogr ...
- SpringMVC拦截器2(资源和权限管理)(作为补充说明)
SpringMVC拦截器(资源和权限管理) 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServle ...
- DNS-解析、劫持、污染
DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工 ...
- Get Files from Directory
http://www.csharp-examples.net/get-files-from-directory/ Get Files from Directory [C#] This example ...
- 最详细的 HTTPS 科普扫盲帖
为什么需要https HTTP是明文传输的,也就意味着,介于发送端.接收端中间的任意节点都可以知道你们传输的内容是什么.这些节点可能是路由器.代理等. 举个最常见的例子,用户登陆.用户输入账号,密码, ...
- Linux系统从安装开始
已经很久很久没来得及写博客了,想想之前自己开始安装使用Linux系统的尝试,好像很简单!下面开始Linux系统的安装:这里推荐U盘安装 首先你必须下载一个U盘ISO镜像写入工具,本人使用USBWrit ...
- Linux记录-JMX监控Tomcat上传到falcon
1.登录测试服务器xxxxxx xxxxxx su root输入xxxx 2.先修改Tomcat的启动脚本,(linux下为catalina.sh),添加以下内容: CATALINA_OPTS=&qu ...
- 《Python数据可视化编程实战》
第一章:准备工作环境 WinPython-32bit-3.5.2.2Qt5.exe 1.1 设置matplotlib参数 配置模板以方便各项目共享 D:\Bin\WinPython-32bit-3.5 ...








