P3241 [HNOI2015]开店

题目描述

风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学。最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱。

这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群。很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 \(n\)个地方,编号为 \(1\) 到 \(n\) 被\(n-1\) 条带权的边连接起来。每个地方都住着一个妖怪,其中第 \(i\) 个地方的妖怪年龄是 \(x_i\) 。

妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻。所以这个树所有顶点的度数都小于或等于 \(3\)。妖怪和人一样,兴趣点随着年龄的变化自然就会变化,比如我们的\(18\) 岁少女幽香和八云紫就比较喜欢可爱的东西。幽香通过研究发现,基本上妖怪的兴趣只跟年龄有关,所以幽香打算选择一个地方\(u\) (\(u\) 为编号),然后在\(u\)开一家面向年龄在 \(L\) 到 \(R\) 之间(即年龄大于等于 \(L\) 小于等于 \(R\) )的妖怪的店。

也有可能 \(u\) 这个地方离这些妖怪比较远,于是幽香就想要知道所有年龄在 \(L\) 到 \(R\) 之间的妖怪,到点 \(u\) 的距离的和是多少(妖怪到 \(u\) 的距离是该妖怪所在地方到 \(u\) 的路径上的边的权之和),幽香把这个称为这个开店方案的方便值。

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

输入输出格式

输入格式:

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

第二行 \(n\) 个用空格分开的数\(x_1,x_2,\ldots,x_n;x_i\) 表示第 \(i\) 个地点妖怪的年龄,满足\(0\le x_i\lt A\) 。(年龄是可以为\(0\)的,例如刚出生的妖怪的年龄为\(0\) 。)

接下来 \(n-1\) 行,每行三个用空格分开的数 \(a\) 、\(b\) 、\(c\) ,表示树上的顶点 \(a\) 和 \(b\) 之间有一条权为\(c(1\le c\le1000)\)的边,\(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)\)

输出格式:

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

说明

满足\(n\le1.5\times10^5,Q\le2\times10^5\) 。对于所有数据,满足 \(A\le10^9\)


动态点分=sb码农题+sb卡常题,以上...

要相信同样是两个\(\log\)的算法,有人是\(2s\),有人是\(30s\)

先把点分树弄出来,然后对每个点维护自己在点分树上的子树的每个点到点分树父亲的距离和,最开始我拿的线段树,因为要按年龄划分。

然后预处理是\(O(n\log^2n)\),查询是\(O(\log^2n)\)的

预处理按照点分治那样处理就可以了。

查询暴力向上跳,每次统计一下分治树外的答案+分治树外满足要求的点的个数乘上路径长度。

然后\(ST\)表的一个数组开小了,检查了快\(2h...\),然后卡常也卡不动,本地开\(10s\)才能勉强跑过去。注意这里年龄要先离散化,不然线段树开不下。

考虑没有查询可以直接前缀和,统计的时候拿\(vector\)存一下前缀和然后差分进行询问。询问的时候需要二分一下但是常数就小很多了。

然后咕咕不吸氧还是过不去...


Code:

// luogu-judger-enable-o2
#include <cstdio>
#include <vector>
#include <cctype>
#include <algorithm>
#define ll long long
const int N=150010;
using std::min;
using std::max;
int head[N],to[N<<1],Next[N<<1],edge[N<<1],cnt;
void add(int u,int v,int w)
{
to[++cnt]=v,Next[cnt]=head[u],edge[cnt]=w,head[u]=cnt;
}
char c;int xx;
int read()
{
c=getchar();xx=0;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {xx=xx*10+c-'0';c=getchar();}
return xx;
}
namespace RMQLCA
{
int dfn[N],st[N<<1][20],dep[N],Log[N<<1],dfs_clock;ll dis[N];
void dfs(int now,int fa)
{
dep[now]=dep[fa]+1;
st[dfn[now]=++dfs_clock][0]=now;
for(int v,i=head[now];i;i=Next[i])
if((v=to[i])!=fa)
dis[v]=dis[now]+edge[i],dfs(v,now),st[++dfs_clock][0]=now;
}
void init()
{
dfs(1,0);
for(int i=2;i<=dfs_clock;i++) Log[i]=Log[i>>1]+1;
for(int j=1;j<=19;j++)
{
for(int x,y,i=1;i<=dfs_clock-(1<<j)+1;i++)
{
x=st[i][j-1],y=st[i+(1<<j-1)][j-1];
st[i][j]=dep[x]<dep[y]?x:y;
}
}
}
ll getdis(int x,int y)
{
ll ret=dis[x]+dis[y];
x=dfn[x],y=dfn[y];
if(x>y) std::swap(x,y);
int d=Log[y+1-x];
x=st[x][d],y=st[y-(1<<d)+1][d];
return ret-(dis[dep[x]<dep[y]?x:y]<<1);
}
}
struct node
{
int age,ct;ll f;
bool friend operator <(node n1,node n2){return n1.age<n2.age;}
};
std::vector <node> sum[N];
std::vector <node>::iterator it;
ll su1=0,su2=0;
void query0(int now,int R)
{
it=std::upper_bound(sum[now].begin(),sum[now].end(),(node){R,0,0});
if(it!=sum[now].begin())
it--,su1=it->f,su2=it->ct;
else
su1=su2=0;
}
int mi,rt,si,siz[N],del[N],par[N];
int n,q,m,poi[N],b[N];ll maxn;
void dfs1(int now,int fa)
{
siz[now]=1;int mx=0;
for(int v,i=head[now];i;i=Next[i])
if(!del[v=to[i]]&&v!=fa)
dfs1(v,now),siz[now]+=siz[v],mx=mx>siz[v]?mx:siz[v];
mx=mx>si-siz[now]?mx:si-siz[now];
if(mi>mx) mi=mx,rt=now;
}
void dfs2(int now,int fa,int w,ll dis)
{
sum[w].push_back((node){poi[now],0,dis});
for(int v,i=head[now];i;i=Next[i])
if(!del[v=to[i]]&&v!=fa)
dfs2(v,now,w,dis+edge[i]);
}
std::vector <int> Edge[N];
void deal(int now)
{
std::sort(sum[now].begin(),sum[now].end());
sum[now][0].ct=1;
for(int i=1;i<sum[now].size();i++)
sum[now][i].f+=sum[now][i-1].f,sum[now][i].ct=i+1;
}
void divide(int now)
{
del[now]=1;
for(int w,v,i=head[now];i;i=Next[i])
{
if(!del[w=to[i]])
{
mi=N,si=siz[w],dfs1(w,0);
dfs2(w,0,v=rt,edge[i]);
deal(v);
par[v]=now,Edge[now].push_back(v);
divide(v);
}
}
}
void getsum(int now,int v,int R,ll &ret1,ll &ret2)
{
ret1=ret2=0;
for(int w,i=0;i<Edge[now].size();i++)
if((w=Edge[now][i])!=v)
su1=su2=0,query0(w,R),ret1+=su1,ret2+=su2;
ret2+=poi[now]<=R;
}
ll query(int now,int R)
{
int las=now;ll ret1,ret2;
getsum(now,0,R,ret1,ret2);
ll ret=ret1;
while(par[now])
{
getsum(par[now],now,R,ret1,ret2);
ret+=ret1;
ret+=ret2*RMQLCA::getdis(las,par[now]);
now=par[now];
}
return ret;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("dew.out","w",stdout);
n=read(),q=read(),maxn=read();
for(int i=1;i<=n;i++) poi[i]=read();
for(int u,v,w,i=1;i<n;i++)
{
u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
RMQLCA::init();
mi=N,si=n;dfs1(1,0),divide(rt);
ll lastans=0;
for(int u,l,r,i=1;i<=q;i++)
{
u=read(),l=read(),r=read();
l=(l+lastans)%maxn,r=(r+lastans)%maxn;
if(l>r) std::swap(l,r);
printf("%lld\n",lastans=(query(u,r)-query(u,l-1)));
}
return 0;
}

2018.12.6

洛谷 P3241 [HNOI2015]开店 解题报告的更多相关文章

  1. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  2. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  3. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  4. 洛谷 P3349 [ZJOI2016]小星星 解题报告

    P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...

  5. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  6. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

  7. 洛谷 P1272 重建道路 解题报告

    P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...

  8. 洛谷 [HNOI2014]道路堵塞 解题报告

    [HNOI2014]道路堵塞 题意 给一个有向图并给出一个这个图的一个\(1\sim n\)最短路,求删去这条最短路上任何一条边后的最短路. 又事SPFA玄学... 有个结论,新的最短路一定是\(1\ ...

  9. 洛谷 P1452 Beauty Contest 解题报告

    P1452 Beauty Contest 题意 求平面\(n(\le 50000)\)个点的最远点对 收获了一堆计算几何的卡点.. 凸包如果不保留共线的点,在加入上凸壳时搞一个相对栈顶,以免把\(n\ ...

随机推荐

  1. 世界杯足彩怎么买划算?机器学习AI告诉你答案(含预测)

    本文首发于InfoQ公众号头条. 四年一度的世界杯又来了,作为没什么时间看球的码农,跟大家一样,靠买买足彩给自己点看球动力和乐趣, 然而总是买错球队,面对各种赔率也不知道怎么买才划算,足彩是不是碰大运 ...

  2. selenium自动化之定位多个元素

    前面我们讲的都是如何定位单个元素,下面讲下怎么去定位多个元素,并且输出文本. 以百度为例:获取标红的这一组元素的文本 这里我用到的是xpath来定位的://div[@id="u1" ...

  3. Echarts-K线图提示框改头换面

    工作: 使用Hbuilder建web工程,加入echarts相关库,根据需要更改K线图及其的提示样式,去除默认提示,使用异步加载echarts的数据,数据格式为json. 需要注意的K线图和5日均线, ...

  4. OpenLDAP配置TLS加密传输

    原文发表于cu:2016-07-04 参考文档: 基于OpenSSL自建CA与颁发SSL证书:http://seanlook.com/2015/01/18/openssl-self-sign-ca/ ...

  5. arcgis--arcmap导出点的X,Y坐标

    arcmap操作的

  6. kafka相关文章引用

    kafka相关内容说明: Kafka压缩 Kafka端到端审计 kafka数据可靠性深度解读 Kafka发送超过broker限定大小的消息时Client和Broker端各自会有什么异常? Kafka之 ...

  7. 【转】SWFUpload 官方说明文档(2.5.0版)

    原文出自:http://www.runoob.com/w3cnote/swfupload-document.html SWFUpload使用指南请查阅:http://www.w3cschool.cc/ ...

  8. 带你玩转JavaScript中的隐式强制类型转换

    正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较 ...

  9. 跨域写cookie

    假设a站想往b站写cookie,那么目前有两种方案,参考如下: 第一种(使用jsonp): a站js代码如下: $.ajax({ url: 'http://www.b.com/jsonp.jsp?do ...

  10. 解决zabbix使用中文是出现乱码的问题

       解决zabbix使用中文是出现乱码的问题 ①:上传windows的simhei.ttf字体到zabbix服务器的/usr/share/zabbix/fonts/目录下   ②:编辑/usr/sh ...