【BZOJ】4012: [HNOI2015]开店
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012
给出一个$n$个点的树,树上每一个点都有一个值$age$,每条边都有边权,每次查询一个点,求出树中所有点上权值${L<=age[i]<=R}$的点到它的距离的和。
为了学习传说中的动态树分治,我就把这个题当作模板题来写了。
当然这题也可以树链剖分+权值线段树。
为什么叫做动态树分治?其实就是把分治的结构记录了下来,树分治的好处在于每一次操作(找出当前块重心并再次递归)可以快速减少树的大小,我们记录下这个每次求出的树的重心的结构,这样的分治结构是严格log层的,每一次查询的是沿着分治结构构出的树往上跳,统计所有点到当前点的距离(这里需要数据结构维护,可以开一个vector动态记录每一个点在分治中所管辖的子树的所有点的信息,然后查询的时候二分即可),然后再往分治结构构成的树的父亲上跳,因为在分治结构的父亲所管辖的子树一定包含了当前点所管辖的子树,所以需要容斥(全是细节)。复杂度${O(nlog^{2})}$
可怕的是BZOJ上似乎卡常?
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<ctime>
using namespace std;
#define maxn 600100
#define llg long long
#define RG register llg
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg Q,A,n,m,age[maxn],ans,dad[maxn],dadv[maxn],maxage,f[maxn][],dis[maxn][],deep[maxn];
bool bj[maxn],bj_[maxn];
llg g[maxn<<],maxl,weizhi,dl[maxn],tail,L,R,o,te,buf[]; inline void write(RG x)
{
if (x<) putchar('-'),x=-x;
buf[]=;
while (x) buf[++buf[]]=x%,x/=;
if (!buf[]) buf[]=,buf[]=;
while (buf[]) putchar(''+buf[buf[]--]);
putchar('\n');
} inline llg getint()
{
llg w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} struct edge{
int y,next;
llg d;
}e[maxn<<]; void addedge(RG x,RG y,RG d){
e[++te].y=y;
e[te].d=d;
e[te].next=g[x];
g[x]=te;
} struct node
{
llg age,dis,qz,qz_,dis_;
};
inline bool cmp(const node&a,const node&b) {return a.age<b.age;} vector<node>c[maxn]; inline void clear_() {for (RG i=;i<=tail;i++) bj_[dl[i]]=; tail=;} inline void dfs(RG x,RG fa)
{
for (RG i=g[x];i;i=e[i].next)
{
RG v=e[i].y;
if (v==fa) continue;
f[v][]=x; dis[v][]=e[i].d;
deep[v]=deep[x]+;
dfs(v,x);
}
} inline void make_f()
{
for (RG j=;j<=;j++)
for (RG i=;i<=n;i++)
{
f[i][j]=f[f[i][j-]][j-];
dis[i][j]=dis[i][j-]+dis[f[i][j-]][j-];
}
} inline llg find_dis(RG x,RG y)
{
if (x== || y==) return ;
RG ans=;
if (deep[x]<deep[y]) swap(x,y);
for (RG i=;i>=;i--)
if (deep[f[x][i]]>=deep[y])
{
ans+=dis[x][i];
x=f[x][i];
}
if (x==y) return ans;
for (RG i=;i>=;i--)
if (f[x][i]!=f[y][i])
{
ans+=dis[x][i]+dis[y][i];
x=f[x][i],y=f[y][i];
}
return ans+dis[x][]+dis[y][];
} void init()
{
RG x,y,z;
cin>>n>>Q>>A;
for (RG i=;i<=n;i++) age[i]=getint(),maxage=max(maxage,age[i]);
for (RG i=;i<n;i++)
{
x=getint(),y=getint(),z=getint();
addedge(x,y,z);
addedge(y,x,z);
}
deep[]=;
dfs(,);
make_f();
} inline llg find_size(RG x)
{
bj_[x]=;
dl[++tail]=x;
RG tot=;
for (RG i=g[x];i;i=e[i].next)
{
RG v=e[i].y;
if (bj[v] || bj_[v]) continue;
tot+=find_size(v);
}
return tot;
} inline llg dp(RG x,RG size)
{
bj_[x]=;
dl[++tail]=x;
RG tot=,ma=;
for (register llg i=g[x];i;i=e[i].next)
{
RG v=e[i].y;
if (bj[v] || bj_[v]) continue;
RG he=dp(v,size);
ma=max(ma,he);
tot+=he;
}
ma=max(size-tot,ma);
if (ma<maxl)
{
maxl=ma;
weizhi=x;
}
return tot;
} inline llg find_root(RG x)
{
clear_();
RG size=find_size(x);
clear_();
maxl=n+; weizhi=-;
dp(x,size);
return weizhi;
} inline void dfs_c(RG x,RG now)
{
bj_[x]=; dl[++tail]=x;
node E;
E.age=age[x]; E.dis=find_dis(x,now); E.dis_= find_dis(x,dad[now]);
c[now].push_back(E);
for (RG i=g[x];i;i=e[i].next)
{
RG v=e[i].y;
if (bj[v] || bj_[v]) continue;
dfs_c(v,now);
}
} inline void solve( RG now,RG fa)
{
RG ne=find_root(now);
now=ne;
dadv[now]=find_dis(now,fa);
bj[now]=;
dad[now]=fa;
clear_();
dfs_c(now,now);
for (RG i=g[now];i;i=e[i].next)
{
RG v=e[i].y;
if (bj[v]) continue;
solve(v,now);
}
RG si=c[now].size();
sort(c[now].begin(),c[now].end(),cmp);
c[now][].qz=c[now][].dis;
c[now][].qz_=c[now][].dis_;
for (RG i=;i<si;i++)
{
c[now][i].qz=c[now][i-].qz+c[now][i].dis;
c[now][i].qz_=c[now][i-].qz_+c[now][i].dis_;
}
} void read() {RG x,y; x=getint(),y=getint(); L=min((x+ans)%A,(y+ans)%A); R=max((x+ans)%A,(y+ans)%A);} inline llg erfen(RG x, RG V,RG dis_,bool pd)
{
RG l=,r=c[x].size()-,mid,wz=-;
while (l<=r)
{
mid=(l+r)>>;
if (c[x][mid].age<=V) {wz=mid; l=mid+;}else{r=mid-;}
}
if (wz==-) return ;
if (pd) return c[x][wz].qz+(dis_-find_dis(dad[x],o))*(wz+)-c[x][wz].qz_;
else return c[x][wz].qz_+(wz+)*(find_dis(dad[x],o)-dis_)-c[x][wz].qz;
} inline llg erfen_(RG x,RG V)
{
RG l=,r=c[x].size()-,mid,wz=-;
while (l<=r)
{
mid=(l+r)>>;
if (c[x][mid].age<=V) {wz=mid; l=mid+;}else{r=mid-;}
}
if (wz==-) return ;
return (wz+)*find_dis(dad[x],o)+c[x][wz].qz_;
} inline void find(register llg x)
{
RG dis_=find_dis(x,o);
// llg sum=erfen(x,R,dis_)-erfen(x,L-1,dis_);
// llg dec=erfen_(x,R)-erfen_(x,L-1);
ans+=erfen(x,R,dis_,)+erfen(x,L-,dis_,);
// ans+=sum-dec;
if (dad[x]!=) find(dad[x]);
} llg dg(llg x)
{
if (dad[x]!=) return dg(dad[x])+;
else return ;
} int main()
{
yyj("shop");
init();
solve(,);
/* for (llg i=1;i<=n;i++)
{
maxl=max(maxl,dg(i));
}
cout<<maxl; return 0;*/
while (Q--)
{
o=getint();
read();
ans=;
find(o);
write(ans);
}
// cout<<clock();
return ;
}
【BZOJ】4012: [HNOI2015]开店的更多相关文章
- bzoj 4012: [HNOI2015]开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- bzoj 4012: [HNOI2015]开店 主席树
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ 4012 HNOI2015 开店 树的边分治+分治树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012 题意概述:给出一颗N点的树,保证树上所有点的度不超过3,树上每个点有权值,每条边有权 ...
- BZOJ 4012 [HNOI2015]开店 (树分治+二分)
题目大意: 给你一棵树,边有边权,点有点权,有很多次询问,求点权$\in[l,r]$的所有节点到某点$x$的距离之和,强制在线 感觉这个题应该放在动态点分之前做= = 套路方法和动态点分是一样的 每次 ...
- BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)
讲得好啊 主席树区间修改了,每一次遇到整区间就打永久化标记(不下传,访问的时候沿路径上的标记算答案)然后returnreturnreturn,那么每修改一次只会访问到lognlognlogn个节点,再 ...
- [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)
4012: [HNOI2015]开店 Time Limit: 70 Sec Memory Limit: 512 MBSubmit: 2168 Solved: 947[Submit][Status] ...
- [HNOI2015]开店 树链剖分,主席树
[HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...
- 洛谷 P3241 [HNOI2015]开店 解题报告
P3241 [HNOI2015]开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想法当然非 ...
- Luogu 3241 [HNOI2015]开店
BZOJ 4012权限题 浙科协的网突然炸了,好慌…… 据说正解是动态点分治,然而我并不会,我选择树链剖分 + 主席树维护. 设$dis_i$表示$i$到$root(1)$的值,那么对于一个询问$u$ ...
随机推荐
- PHP操作Redis常用技巧
这篇文章主要介绍了PHP操作Redis常用技巧,结合实例形式总结分析了php针对redis的连接.认证.string.hash等操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了PHP操作Red ...
- [LeetCode] 104. Maximum Depth of Binary Tree_Easy tag: DFS
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...
- html08
1.JQuery 是一个js框架一堆的 js文件 -形成 > 包 - 形成> 工具 - 形成> ->库 -> 框架 是一个轻量级的库 封装了js原生里js css dom ...
- cocos2dx-环境搭建和创建项目(mac用)
学习一门语言最快的方法就是制作一个简单的项目. 而要制作一个项目必须先搭好环境,即使花上2小时去熟悉环境创建也不算浪费.由于之后的项目会用到cocos2d-x 3.0,这里以3.0为例子(不同的版本写 ...
- 如何向GLSL中传入多个纹理
http://blog.csdn.net/huawenguang/article/details/41245871 如何向GLSL中传入多个纹理 这几天在研究如何实现用GLSL对多个纹理进行融合处理, ...
- Kafka学习之(五)搭建kafka集群之Zookeeper集群搭建
Zookeeper是一种在分布式系统中被广泛用来作为:分布式状态管理.分布式协调管理.分布式配置管理.和分布式锁服务的集群.kafka增加和减少服务器都会在Zookeeper节点上触发相应的事件kaf ...
- 05: jQuery
目录: jQuery参考网站 W3school 1.1 JQuery作用 1.2 jQuery与DOM比较 与 相互转换 1.3 jQuery选择器 1.4 jQuery筛选与过滤 1.5 jQuer ...
- htm5之视频音频(shit IE10都不支持)
<p style="color: red; background-color: black;"> 视频<br /> autoplay autoplay 如果 ...
- 20145122 《Java程序设计》课程总结
课程总结 每周读书笔记链接汇总 第一周读书笔记:http://www.cnblogs.com/20145122chengzhiyin/p/5244949.html 第二周读书笔记:http://www ...
- 20145314郑凯杰《网络对抗技术》恶意DLL注入进程(进程捆绑)的实现
20145314郑凯杰<网络对抗技术>恶意DLL注入进程(进程捆绑)的实现 一.本节摘要 简介:在这部分里,要实现将恶意后门悄无声息地与进程进行捆绑,通过和已运行的进程进行捆绑,达到附着攻 ...