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. Flask开发环境搭建

    基础准备 Python 3.6.5 Conda Visual Studio Code 虚拟环境 创建虚拟环境 conda create -n flask 激活虚拟环境 activate flask 关 ...

  2. 帮你理解学习lambda式

    概要     窗前明月光,疑是地上霜,举头望明月,低头思故乡.别误会这是开头诗与以下文章没任何关系. 今天我想给大家说道说道 C# lambda表达式,不废话,下面开始说道! lambda lambd ...

  3. TensorFlow深度学习实战---循环神经网络

    循环神经网络(recurrent neural network,RNN)-------------------------重要结构(长短时记忆网络( long short-term memory,LS ...

  4. Linux查看文件内容

    查看文件内容的命令: cat:连接文件并且打印在标准输出 tac:连接并且倒序打印文件 more:屏幕文件熟读过滤器 less head:输出文件的第一部分 tail:输出文件最后的部分 nl:输出文 ...

  5. 测试类异常Manual close is not allowed over a Spring managed SqlSession

    在用Spring 和mybatis整合的 写测试类的时候报出解决办法:在全局配置文件   class="org.mybatis.spring.SqlSessionTemplate" ...

  6. nginx main函数

    源代码: int ngx_cdecl main(int argc, char *const *argv) { ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cyc ...

  7. 5个最优秀的微信小程序UI组件库

    开发微信小程序的过程中,选择一款好用的组件库,可以达到事半功倍的效果.自从微信小程序面世以来,不断有一些开源组件库出来,下面5款就是排名比较靠前,用户使用量与关注度比较高的小程序UI组件库.还没用到它 ...

  8. sqlserver-查阻塞

    模拟阻塞: 打开两个窗口:     窗口一: BEGIN TRANSACTION--开始事务 --等待1分钟 WAITFOR DELAY '00:1'; 窗口二: 查询阻塞:(当前被阻塞的进程id,不 ...

  9. 《JavaScript设计模式与开发实践》——第3章 闭包和高阶函数

    闭包 变量的作用域和生存周期密切相关 高阶函数 函数可以作为参数被传递 函数可以作为返回值输出

  10. 【每日scrum】NO.8

    (1) 在图的设计过程中掌握了图的基本运算函数的算法的理解和程序的有效吸收,包括图的深度和广度优先的遍历,对图的联通分量的求解,图的最小生成树,图的拓扑排序,图的关键路径, (2)在迪杰斯特拉算法的基 ...