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. textbox的验证

    代码如下: textBox1.KeyDown += (a, b) => { if (b.KeyCode == Keys.Enter) { textBox2.Focus(); } }; textB ...

  2. MySQL数据库之单双表查询

    单表查询 先创建表 #创建表 create table employee( id int not null unique auto_increment, name varchar(20) not nu ...

  3. tomcat 部署项目到服务器

    参考博客,我选了一种最简单的方法来部署项目. 在tomcat 目录下 的  conf\Catalina\localhost 目录中,新建一个   ' 项目名.xml '   文件,名字用项目名表示, ...

  4. Web自动化常用方法封装(不定时更新)

    /** * JScript实现鼠标悬停 */public void mouseHoverJScript(By by,WebElement HoverElement) { // TODO Auto-ge ...

  5. zabbix_agentd-install.sh (脚本部署zabbix_agentd服务)

    原文发表于cu:2016-05-20 基于http://www.cnblogs.com/netonline/p/7406598.html(http://blog.chinaunix.net/uid-2 ...

  6. 手机上Uncaught ReferenceError: __WEBPACK_AMD_DEFINE_ARRAY__ is not defined的错误

    问题: vue2.0和webpack2.X的写的项目在电脑的浏览器上打开正常,在手机浏览器中访问页面的时候不能正常显示,空白. 通过chrome的真机调试chrome://inspect/#devic ...

  7. Intense Heat(前缀和或尺取)

    The heat during the last few days has been really intense. Scientists from all over the Berland stud ...

  8. 20172311-ASL测试 2018-1938872补充博客

    20172311-ASL测试 2018-1938872补充博客 课程:<程序设计与数据结构> 班级: 1723 姓名: 赵晓海 学号: 20172311 实验教师:王志强老师 测试日期:2 ...

  9. 学习调用第三方的WebService服务

    互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的应用中显示,下面就以查询国内手机号码归属地为例进行说明. 首先安利一 ...

  10. 第一次c++团队合作项目第三篇随笔

    这次终于想出来了上次问题的解决方法,就是用多态的方法,让小兵,建筑和英雄继承于Object类,通过指针能实现信息的传递. 同时我也完善了地图中每个Pane类的信息,包括每个格子的位置信息,state( ...