【BZOJ4012】开店(主席树)
【BZOJ4012】开店(主席树)
题面
Description
风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到
人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的
想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面
向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n
个地方,编号为 1 到 n,被 n-1 条带权的边连接起来。每个地方都住着一个妖怪,
其中第 i 个地方的妖怪年龄是 x_i。妖怪都是些比较喜欢安静的家伙,所以它们并
不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 3。妖怪和人一
样,兴趣点随着年龄的变化自然就会变化,比如我们的 18 岁少女幽香和八云紫就
比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以
幽香打算选择一个地方 u(u为编号),然后在 u开一家面向年龄在 L到R 之间(即
年龄大于等于 L、小于等于 R)的妖怪的店。也有可能 u这个地方离这些妖怪比较
远,于是幽香就想要知道所有年龄在 L 到 R 之间的妖怪,到点 u 的距离的和是多
少(妖怪到 u 的距离是该妖怪所在地方到 u 的路径上的边的权之和) ,幽香把这个
称为这个开店方案的方便值。幽香她们还没有决定要把店开在哪里,八云紫倒是准
备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。
Input
第一行三个用空格分开的数 n、Q和A,表示树的大小、开店的方案个数和妖
怪的年龄上限。
第二行n个用空格分开的数 x_1、x_2、…、x_n,x_i 表示第i 个地点妖怪的年
龄,满足0<=x_i<A。(年龄是可以为 0的,例如刚出生的妖怪的年龄为 0。)
接下来 n-1 行,每行三个用空格分开的数 a、b、c,表示树上的顶点 a 和 b 之
间有一条权为c(1 <= c <= 1000)的边,a和b 是顶点编号。
接下来Q行,每行三个用空格分开的数 u、 a、 b。对于这 Q行的每一行,用 a、
b、A计算出 L和R,表示询问“在地方 u开店,面向妖怪的年龄区间为[L,R]的方
案的方便值是多少”。对于其中第 1 行,L 和 R 的计算方法为:L=min(a%A,b%A),
R=max(a%A,b%A)。对于第 2到第 Q行,假设前一行得到的方便值为 ans,那么当
前行的 L 和 R 计算方法为: L=min((a+ans)%A,(b+ans)%A),
R=max((a+ans)%A,(b+ans)%A)。
Output
对于每个方案,输出一行表示方便值。
Sample Input
10 10 10
0 0 7 2 1 4 7 7 7 9
1 2 270
2 3 217
1 4 326
2 5 361
4 6 116
3 7 38
1 8 800
6 9 210
7 10 278
8 9 8
2 8 0
9 3 1
8 0 8
4 2 7
9 7 3
4 7 0
2 2 7
3 2 1
2 3 4
Sample Output
1603
957
7161
9466
3232
5223
1879
1669
1282
0
HINT
满足 n<=150000,Q<=200000。对于所有数据,满足 A<=10^9
题解
这道题目和BZOJ3626 LCA很相似
所以现在就可以考虑像上面那道题目一样的
向链上打标记
但是考虑到有年龄的限制
所以需要用主席树
还有就是空间可能开不下
要标记永久化
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 200000
#define ll long long
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line
{
int v,next,w;
}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w)
{
e[cnt]=(Line){v,h[u],w};h[u]=cnt++;
}
int n,Q,A,Age[MAX],S[MAX],tot;
/***********************************************************************/
int dfn[MAX],dis[MAX],top[MAX],size[MAX],hson[MAX],fa[MAX];
int tim,ln[MAX];
void dfs1(int u,int ff)
{
fa[u]=ff;size[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==ff)continue;
dis[v]=dis[u]+e[i].w;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim;ln[tim]=u;
if(hson[u])dfs2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa[u]||v==hson[u])continue;
dfs2(v,v);
}
}
/***********************************************************************/
struct Node
{
int ls,rs;
ll sum;
ll lz;
}t[MAX<<6];
int Cnt;
bool cmp(int a,int b){return Age[a]<Age[b];}
void Build(int &now,int l,int r)
{
now=++Cnt;
if(l==r)return;
int mid=(l+r)>>1;
Build(t[now].ls,l,mid);
Build(t[now].rs,mid+1,r);
}
void Modify(int &now,int l,int r,int al,int ar)
{
t[++Cnt]=t[now];now=Cnt;
t[now].sum+=dis[ln[ar]]-dis[fa[ln[al]]];
if(l==al&&r==ar){t[now].lz++;return;}
int mid=(l+r)>>1;
if(ar<=mid)Modify(t[now].ls,l,mid,al,ar);
else if(al>mid)Modify(t[now].rs,mid+1,r,al,ar);
else
{
Modify(t[now].ls,l,mid,al,mid);
Modify(t[now].rs,mid+1,r,mid+1,ar);
}
}
ll Query(int now,int l,int r,ll ly,int al,int ar)
{
if(l==al&&r==ar)return t[now].sum+1ll*ly*(dis[ln[ar]]-dis[fa[ln[al]]]);
int mid=(l+r)>>1;
if(ar<=mid)return Query(t[now].ls,l,mid,ly+t[now].lz,al,ar);
if(al>mid)return Query(t[now].rs,mid+1,r,ly+t[now].lz,al,ar);
return Query(t[now].ls,l,mid,ly+t[now].lz,al,mid)+Query(t[now].rs,mid+1,r,ly+t[now].lz,mid+1,ar);
}
/***********************************************************************/
ll sdis[MAX];
int rt[MAX],id[MAX];
ll Calc(int u,int K)
{
ll ret=0;
while(top[u]!=1)ret+=Query(rt[K],1,n,0,dfn[top[u]],dfn[u]),u=fa[top[u]];
ret+=Query(rt[K],1,n,0,1,dfn[u]);
return ret;
}
int main()
{
n=read();Q=read();A=read();
for(int i=1;i<=n;++i)id[i]=i,Age[i]=read(),S[++tot]=Age[i];
sort(&S[1],&S[n+1]);
sort(&id[1],&id[n+1],cmp);
for(int i=1;i<n;++i)
{
int u=read(),v=read(),C=read();
Add(u,v,C);Add(v,u,C);
}
dfs1(1,0);dfs2(1,1);
Build(rt[0],1,n);
for(int i=1;i<=n;++i)
{
int x=id[i];
sdis[i]=sdis[i-1]+dis[x];
rt[i]=rt[i-1];
while(top[x]!=1)
Modify(rt[i],1,n,dfn[top[x]],dfn[x]),x=fa[top[x]];
Modify(rt[i],1,n,1,dfn[x]);
}
ll ans=0;
int L,R;
while(Q--)
{
ll u=read(),a=read(),b=read();
L=min((ans+a)%A,(ans+b)%A);
R=max((ans+a)%A,(ans+b)%A);
L=lower_bound(&S[1],&S[tot+1],L)-S;
R=lower_bound(&S[1],&S[tot+1],R+1)-S-1;
ans=1ll*(R-L+1)*dis[u]+sdis[R]-sdis[L-1]-2ll*(Calc(u,R)-Calc(u,L-1));
printf("%lld\n",ans);
}
return 0;
}
【BZOJ4012】开店(主席树)的更多相关文章
- bzoj 4012: [HNOI2015]开店 主席树
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- BZOJ4012 HNOI2015开店(树链剖分+主席树)
考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑:询问某点到所有黑点的距离之和. 注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2.要求 ...
- [HNOI2015]开店 树链剖分,主席树
[HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...
- [HNOI2015]开店(树剖+主席树+标记永久化)
听说正解点分树?我不会就对了 此题是 \([LNOI2014]LCA\) 强化版,也是差分一下,转化为区间加区间和 不过权值有大小要求,那么我们按照权值排序,依次加入主席树,询问的时候 \(lower ...
- BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)
讲得好啊 主席树区间修改了,每一次遇到整区间就打永久化标记(不下传,访问的时候沿路径上的标记算答案)然后returnreturnreturn,那么每修改一次只会访问到lognlognlogn个节点,再 ...
- 洛谷$P$3241 开店 $[HNOI2015]$ 主席树/点分治
正解:主席树/动态点分治 解题报告: 传送门! $umm$淀粉质的话要是动态的我还不会$QAQ$,,,所以先写下主席树的题解昂$QwQ$ 题目大意是说,给定一棵树,树上每个点都有个值,然后有若干个询问 ...
- BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)
BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...
- bzoj3207--Hash+主席树
题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...
- bzoj1901--树状数组套主席树
树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...
随机推荐
- ES6标准入门 第一章:简介
ECMAScript 6 是JavaScript 语言的下一代标准:发布于2015年,又称为ECMAScript 2015. ECMAScript 与 JavaScript 的关系:前者是后者的规范, ...
- php读取文件内容的三种方法
<?php //**************第一种读取方式***************************** 代码如下: header("content-type:text/h ...
- iOS 开发之 Xcode installation failed invalid argument!
1.运行模拟器的时候 报出:installation failed invalid argument! 原因分析:我把Bundle indentifier 置为空了! http://stackover ...
- 置换群、Burnside引理与等价类计数问题
置换群.Burnside引理与等价类计数问题 标签: 置换群 Burnside引理 置换 说说我对置换的理解,其实就是把一个排列变成另外一个排列.简单来说就是一一映射.而置换群就是置换的集合. 比如\ ...
- 基于jq的表单填充
//表单填充 formDataLoad: function (domId, obj) { for (var property in obj) { if (obj.hasOwnProperty(prop ...
- mysql有多条记录的单个字段想存为一个字段显示的方法
SELECT po.id,(SELECT GROUP_CONCAT(mr.member_type) as memberTypeList FROM prod_offer_member_rel mr WH ...
- Java JMS 程序基础 与 ActiveMQ 安装(一)
一 ActiveMQ安装 从Apache官网上下载 ActivieMQ的安装包 apache-activemq-5.9.1-bin.tar.gz, 并拷贝到linux的安装目录解压 # tar -zx ...
- JPA数据懒加载LAZY和实时加载EAGER(二)
懒加载LAZY和实时加载EAGER的概念,在各种开发语言中都有广泛应用.其目的是实现关联数据的选择性加载,懒加载是在属性被引用时,才生成查询语句,抽取相关联数据.而实时加载则是执行完主查询后,不管是否 ...
- Laravel框架中Form表单Get请求搜索(在此感谢[https://simon8.com])
首先看一下HTML部分的Form表单 <form role="search" method="get" id="searchform" ...
- onCreate源码分析
原文地址Android面试题-onCreate源码都没看过,怎好意思说自己做android Activity扮演了一个界面展示的角色,堪称四大组件之首,onCreate是Activity的执行入口,都 ...