#2116. 「HNOI2015」开店

题目描述

风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群。

很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 nnn 个地方,编号为 111 到 nnn,被 n−1n-1n−1 条带权的边连接起来。每个地方都住着一个妖怪,其中第 iii 个地方的妖怪年龄是 xix_ix​i​​。妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 333。妖怪和人一样,兴趣点随着年龄的变化自然就会变化,比如我们的 181818 岁少女幽香和八云紫就比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以幽香打算选择一个地方 uuu(uuu 为编号),然后在 uuu 开一家面向年龄在 LLL 到 RRR 之间(即年龄大于等于 LLL、小于等于 RRR)的妖怪的店。也有可能 uuu 这个地方离这些妖怪比较远,于是幽香就想要知道所有年龄在 LLL 到 RRR 之间的妖怪,到点 uuu 的距离的和是多少(妖怪到 uuu 的距离是该妖怪所在地方到 uuu 的路径上的边的权之和) ,幽香把这个称为这个开店方案的方便值。

幽香她们还没有决定要把店开在哪里,八云紫倒是准备了很多方案,于是幽香想要知道,对于每个方案,方便值是多少呢。

输入格式

第一行三个用空格分开的数 n,Q,An,Q,An,Q,A,表示树的大小、开店的方案个数和妖怪的年龄上限。

第二行 nnn 个用空格分开的数 x1,x2,…,xn,xix_ix​i​​ 表示第 iii 个地点妖怪的年龄,满足 0≤xi<A0 \le x_i < A0≤x​i​​<A。(年龄是可以为 000 的,例如刚出生的妖怪的年龄为 000)

接下来 n−1n-1n−1 行,每行三个用空格分开的数 a,b,ca,b,ca,b,c,表示树上的顶点 aaa 和 bbb 之间有一条权为 ccc(1≤c≤10001 \le c \le 10001≤c≤1000)的边,aaa 和 bbb 是顶点编号。

接下来 QQQ 行,每行三个用空格分开的数 u,a,bu, a, bu,a,b。对于这 QQQ 行的每一行,用 a,b,Aa, b, Aa,b,A 计算出 LLL 和 RRR,表示询问“在地方 uuu 开店,面向妖怪的年龄区间为 [L,R][L,R][L,R] 的方案的方便值是多少”。对于其中第 111 行,LLL 和 RRR 的计算方法为:L=min(amodA,bmodA),R=max(amodA,bmodA)。对于第 222 到第 QQQ 行,假设前一行得到的方便值为 ans\mathrm{ans}ans,那么当前行的 LLL 和 RRR 计算方法为: L=min((a+ans)modA,(b+ans)modA), R=max((a+ans)modA,(b+ans)modA)。

输出格式

对于每个方案,输出一行表示方便值。

样例

样例输入

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

样例输出

1603
957
7161
9466
3232
5223
1879
1669
1282
0

数据范围与提示

对于所有数据,n≤150000n \le 150000n≤150000,Q≤200000Q \le 200000Q≤200000,A≤109A \le 10^9A≤10​9​​。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 3010
using namespace std;
int n,Q,A,w[maxn],head[maxn],num,dis[maxn][maxn];
struct node{int to,pre,v;}e[maxn*];
struct Node{
int id,w;
bool operator < (const Node &b)const{
return w<b.w;
}
}q[maxn];
void Insert(int from,int to,int v){
e[++num].to=to;
e[num].v=v;
e[num].pre=head[from];
head[from]=num;
}
void dfs(int id,int x,int father){
for(int i=head[x];i;i=e[i].pre){
int to=e[i].to;
if(to==father)continue;
dis[id][to]=dis[id][x]+e[i].v;
dfs(id,to,x);
}
}
int findl(int x){
int l=,r=n,res=;
while(l<=r){
int mid=(l+r)>>;
if(q[mid].w>=x)res=mid,r=mid-;
else l=mid+;
}
return res;
}
int findr(int x){
int l=,r=n,res=n+;
while(l<=r){
int mid=(l+r)>>;
if(q[mid].w<=x)res=mid,l=mid+;
else r=mid-;
}
return res;
}
int main(){
scanf("%d%d%d",&n,&Q,&A);
for(int i=;i<=n;i++){
scanf("%d",&w[i]);
q[i].id=i;q[i].w=w[i];
}
sort(q+,q+n+);
int x,y,z;
for(int i=;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
Insert(x,y,z);Insert(y,x,z);
}
for(int i=;i<=n;i++)dfs(i,i,);
int u,a,b,ans=;
while(Q--){
scanf("%d%d%d",&u,&a,&b);
a=(a+ans)%A;
b=(b+ans)%A;
if(a>b)swap(a,b);
int l=findl(a),r=findr(b);
ans=;
for(int i=l;i<=r;i++){
ans+=dis[u][q[i].id];
}
printf("%d\n",ans);
}
return ;
}

20分 暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 150010
using namespace std;
int n,m,A,num,id,rtt,size;
int head[maxn],sz[maxn],fa[maxn],top[maxn],dfn[maxn],lasw[maxn],rt[maxn],son[maxn];
long long ans,sume[maxn],sumdis[maxn],dis[maxn];
struct node{int to,pre,v;}e[maxn*];
struct Node{
int v,id;
bool operator < (const Node &b)const {
if(v!=b.v)return v<b.v;
return id<b.id;
}
}a[maxn];
void Insert(int from,int to,int v){
e[++num].to=to;
e[num].v=v;
e[num].pre=head[from];
head[from]=num;
}
int findl(int x){
int l=,r=n,res=;
while(l<=r){
int mid=(l+r)>>;
if(a[mid].v>=x)r=mid-,res=mid;
else l=mid+;
}
return res;
}
int findr(int x){
int l=,r=n,res=n+;
while(l<=r){
int mid=(l+r)>>;
if(a[mid].v<=x)l=mid+,res=mid;
else r=mid-;
}
return res;
}
//------------------------------------------------------
void dfs1(int x,int father){
sz[x]=;fa[x]=father;
for(int i=head[x];i;i=e[i].pre){
int to=e[i].to;
if(to==father)continue;
dis[to]=dis[x]+e[i].v;
lasw[to]=e[i].v;
dfs1(to,x);
sz[x]+=sz[to];
if(sz[son[x]]<sz[to]||!son[x])son[x]=to;
}
}
void dfs2(int x,int father){
dfn[x]=++id;sume[dfn[x]]=lasw[x];
top[x]=father;
if(son[x])dfs2(son[x],father);
for(int i=head[x];i;i=e[i].pre){
int to=e[i].to;
if((to==fa[x])||(to==son[x]))continue;
dfs2(to,to);
}
}
//------------------------------------------------------
struct TREE{int l,r;long long sum,bj;}tr[];
void chan(int l,int r,int s,int t,int &x,int y) {
x=++size,tr[x]=tr[y];
if(l==s&&t==r) {++tr[x].bj;return;}
tr[x].sum+=sume[r]-sume[l-];
int mid=(s+t)>>;
if(r<=mid) chan(l,r,s,mid,tr[x].l,tr[y].l);
else if(mid+<=l) chan(l,r,mid+,t,tr[x].r,tr[y].r);
else chan(l,mid,s,mid,tr[x].l,tr[y].l),chan(mid+,r,mid+,t,tr[x].r,tr[y].r);
}
long long getans(int l,int r,int s,int t,int x) {
long long res=(sume[r]-sume[l-])*tr[x].bj;
if(l==s&&t==r) return res+tr[x].sum;
int mid=(s+t)>>;
if(r<=mid) return res+getans(l,r,s,mid,tr[x].l);
else if(mid+<=l) return res+getans(l,r,mid+,t,tr[x].r);
else return res+getans(l,mid,s,mid,tr[x].l)+getans(mid+,r,mid+,t,tr[x].r);
}
int work(int x){
while(x){
chan(dfn[top[x]],dfn[x],,n,rtt,rtt);
x=fa[top[x]];
}
return rtt;
}
long long query(int Rt,int x) {
long long res=;
while(x) {
res+=getans(dfn[top[x]],dfn[x],,n,Rt);
x=fa[top[x]];
}
return res;
}
//------------------------------------------------------
int main(){
scanf("%d%d%d",&n,&m,&A);
for(int i=;i<=n;i++){
scanf("%d",&a[i].v);
a[i].id=i;
}
sort(a+,a+n+);
int x,y,z;
for(int i=;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
Insert(x,y,z);Insert(y,x,z);
}
dfs1(,);dfs2(,);
for(int i=;i<=n;i++){
sume[i]+=sume[i-];
sumdis[i]=sumdis[i-]+dis[a[i].id];
}
for(int i=;i<=n;i++)rt[i]=work(a[i].id);
while(m--){
scanf("%d%d%d",&z,&x,&y);
x=((long long)x+ans)%A;
y=((long long)y+ans)%A;
if(x>y)swap(x,y);
x=findl(x);y=findr(y);
ans=1LL*(y-x+)*dis[z]+sumdis[y]-sumdis[x-];
ans-=2LL*(query(rt[y],z)-query(rt[x-],z));
cout<<ans<<endl;
}
return ;
}

100分 线段树+主席树+树剖

loj #2116. 「HNOI2015」开店的更多相关文章

  1. 【LOJ】#2116. 「HNOI2015」开店

    题解 一道我觉得和二叉树没有关系的题-- 因为直接上点分就过了,虽然很慢,而且代码很长 你需要记录一个点分树,对于每个点分树的重心,记录一下上一次进行分割时树的重心以及这个重心和上一次重心所连接的点以 ...

  2. LOJ #2116 Luogu P3241「HNOI2015」开店

    好久没写数据结构了 来补一发 果然写的时候思路极其混乱.... LOJ #2116 Luogu P3241 题意 $ Q$次询问,求树上点的颜色在$ [L,R]$中的所有点到询问点的距离 强制在线 询 ...

  3. [loj2116]「HNOI2015」开店 动态点分治

    4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2452  Solved: 1089[Submit][Status ...

  4. 「HNOI2015」开店(树链剖分, 主席树)

    /* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...

  5. LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)

    题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. Python中的 set 与 深浅拷贝

    字符串 join() 格式:   "拼接的东西".join(可迭代对象) 可以加列表转换成字符串 lis = ['a','b','c','d'] s = "//" ...

  2. python--numpy学习(一)

    NumPy 部分功能如下: ndarray,一个具有矢量运算符和复杂广播能力的快速节省空间的多维数组 用于对数组数据进行快速运算的标准数学函数 用于读写磁盘数据的工具以及用于操作内存映射文件的工具 线 ...

  3. MongoDB在Windows下的环境配置和使用

    总是觉得配置环境是一个超级麻烦的事情啊,而且网上说的又比较乱,配置完后又没有说怎么开始运行,在哪输入增删改查语句,像突然断层一样.所以就在这里详细说说. 一:下载安装 1.去官网的下载页面 2.下载完 ...

  4. component to string 自定义窗体

    component to string string to component StringToComponent ComponentToString ObjectTextToBinary Objec ...

  5. 迷你MVVM框架 avalonjs 0.99发布

    在本版本主要是性能优化,添加一些有用的功能(如回调什么的),离成品阶段不远了. 修正 updateViewModel bug 修正监控数组的set方法 bug 添加data-each-rendered ...

  6. Objective-C入门&nbsp;简介Cocoa框架

    Cocoa Framework简称Cocoa,它是Mac OS X上的快速应用程序开发(RAD, Rapid Application Development)框架,一个高度面向对象的(Object O ...

  7. bash&nbsp;shell笔记7&nbsp;创建函数

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/525126 知 ...

  8. Tarjan的强连通分量算法

    Tarjan算法用于寻找图G(V,E)中的所有强连通分量,其时间复杂度为O(|V|+|E|). 所谓强连通分量就是V的某个极大子集,其中任意两个结点u,v在图中都存在一条从u到v的路径. Tarjan ...

  9. mfs教程(一)

    对于mfs文件系统也用了半年了,确实不错,最近又翻译了作者的三篇文章,再此一同发上,希望对大家有所帮助.不足之处还请指出,以便完善,谢谢! 感谢网友nonamexz做了精美的pdf文档 MFS文件系统 ...

  10. 665. Non-decreasing Array只允许修改一位数的非递减数组

    [抄题]: Given an array with n integers, your task is to check if it could become non-decreasing by mod ...