题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012

题意概述:给出一颗N点的树,保证树上所有点的度不超过3,树上每个点有权值,每条边有权值,现在有Q组询问,每组给出信息u,L,R,问点权在区间[L,R]的点到点u的距离和为多少。强制在线。

N<=150000,Q<=200000.

可能这是我这几天做过的题里面最水但是最码的一个了。。。。

实际上看见树上所有点的度不超过3就感觉可以用边分治做,具体的思路实际上很简单,建立一个边分治结构,这个结构大约有logN层,每层有N个点,对于每组询问,看询问的点u在当前树被分成的两棵子树中的哪一棵,统计出另一个子树中所有点权在询问区间内的点到u的距离,然后递归到u所在的子树,最终就可以计算出答案。

重点在于实现,一不小心处理的时候就会多写出几个常数出来。。。(不要问我是怎么知道的)

实际上这个题我yy的东西重点就在于把边分治建立成一个二叉树的结构然后在里面去搞事情(小火车万岁!),最多有2N个分治结构(每条边会产生2个,有N-1条边)。每一层每个点只会有一个信息,利用这个性质可以记录很多东西,询问的时候在分治结构中递归,令当前分治结构中询问点所在的子树根节点为x,另一边的子树根节点为y(实际上就是断掉的边的两个端点),每一次询问的时候就在y的信息里面二分计算询问区间内点到y的距离,同时得到这些点的数量,然后把从y经过x到u的距离补全累加到答案中,递归。(要点已经交代完了,剩下的请各位自己yy,手动滑稽)

预处理可以用归并排序做到O(nlogn),主要复杂度在查询,单次是O(log2n)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
const int maxd=;
typedef long long LL; int N,Q,A,L,R,age[maxn]; LL ans,dist[maxd][maxn],sum[maxd][maxn];
struct edge{ int to,next,w; }E[maxn<<];
int first[maxn],np,sz[maxn],rt[maxd][maxn];
int ID[maxd][maxn],cnt;
int ke[maxn<<],MAX,ch[maxn<<][],l[maxn<<],r[maxn<<],size[maxd],tot[maxn<<];
bool vis[maxn<<]; void _scanf(int &x)
{
x=;
char cha=getchar();
while(cha<''||cha>'') cha=getchar();
while(cha>=''&&cha<='') x=x*+cha-'',cha=getchar();
}
int out_cnt,out[];
void _printf(LL x)
{
out_cnt=;
out[++out_cnt]=x%,x/=;
while(x) out[++out_cnt]=x%,x/=;
while(out_cnt) putchar(''+out[out_cnt--]);
}
void add_edge(int u,int v,int w)
{
E[++np]=(edge){v,first[u],w};
first[u]=np;
}
void data_in()
{
_scanf(N);_scanf(Q);_scanf(A);
for(int i=;i<=N;i++) _scanf(age[i]);
int x,y,z;
for(int i=;i<N;i++){
_scanf(x);_scanf(y);_scanf(z);
add_edge(x,y,z);
add_edge(y,x,z);
}
}
void DFS(int i,int f,int SZ,int id,int d,LL l)
{
sz[i]=,size[d]++,dist[d][i]=l;
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(j==f||vis[p]) continue;
rt[d][j]=rt[d][i];
DFS(j,i,SZ,id,d,l+E[p].w);
sz[i]+=sz[j];
int tmp=max(sz[j],SZ-sz[j]);
if(tmp<MAX) MAX=tmp,ke[id]=p;
}
}
void merge_sort(int x,int d)
{
int pos=l[x],i=l[ch[x][]],j=r[ch[x][]],r1=r[ch[x][]],r2=r[ch[x][]];
while(i<r1&&j<r2) ID[d][pos++]=age[ID[d+][i]]<age[ID[d+][j]]?ID[d+][i++]:ID[d+][j++];
while(i<r1) ID[d][pos++]=ID[d+][i++];
while(j<r2) ID[d][pos++]=ID[d+][j++];
}
void div_tree(int i,int SZ,int id,int d)
{
MAX=SZ;
l[id]=size[d],rt[d][i]=i;
DFS(i,,SZ,id,d,);
r[id]=size[d];
if((tot[id]=SZ)==){ ID[d][l[id]]=i; return; }
int o0=E[ke[id]].to,o1=E[(ke[id]-^)+].to;
int _sz0=sz[o0],_sz1=SZ-sz[o0];
vis[ke[id]]=vis[(ke[id]-^)+]=;
div_tree(o0,_sz0,ch[id][]=++cnt,d+);
div_tree(o1,_sz1,ch[id][]=++cnt,d+);
merge_sort(id,d);
sum[d][l[id]]=dist[d][ID[d][l[id]]];
for(int j=l[id]+;j<r[id];j++) sum[d][j]=sum[d][j-]+dist[d][ID[d][j]];
}
bool cmp(int x,int y){ return age[x]<age[y]; }
void solve(int p,int id,int d)
{
if(tot[id]==) return;
int x=E[ke[id]].to,y=E[(ke[id]-^)+].to;
int dd=rt[d][p]!=x,t=ch[id][dd^];
age[]=L;
int ll=lower_bound(ID[d]+l[t],ID[d]+r[t],,cmp)-ID[d]-;
LL v1=ll>=l[t]?sum[d][ll]:;
age[]=R;
int rr=upper_bound(ID[d]+l[t],ID[d]+r[t],,cmp)-ID[d]-;
LL v2=rr>=l[t]?sum[d][rr]:;
ans+=v2-v1+(rr-ll)*(E[ke[id]].w+dist[d][p]);
solve(p,ch[id][dd],d+);
}
void work()
{
div_tree(,N,++cnt,);
int u,a,b;
for(int i=;i<=Q;i++){
_scanf(u);_scanf(a);_scanf(b);
L=min((a+ans)%A,(b+ans)%A);
R=max((a+ans)%A,(b+ans)%A);
ans=;
solve(u,,);
_printf(ans),putchar('\n');
}
}
int main()
{
data_in();
work();
return ;
}

BZOJ 4012 HNOI2015 开店 树的边分治+分治树的更多相关文章

  1. BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)

    讲得好啊 主席树区间修改了,每一次遇到整区间就打永久化标记(不下传,访问的时候沿路径上的标记算答案)然后returnreturnreturn,那么每修改一次只会访问到lognlognlogn个节点,再 ...

  2. BZOJ 4012 [HNOI2015]开店 (树分治+二分)

    题目大意: 给你一棵树,边有边权,点有点权,有很多次询问,求点权$\in[l,r]$的所有节点到某点$x$的距离之和,强制在线 感觉这个题应该放在动态点分之前做= = 套路方法和动态点分是一样的 每次 ...

  3. bzoj 4012: [HNOI2015]开店 主席树

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

  4. bzoj 4012: [HNOI2015]开店

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

  5. 【BZOJ】4012: [HNOI2015]开店

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012 给出一个$n$个点的树,树上每一个点都有一个值$age$,每条边都有边权,每次查询一 ...

  6. [BZOJ4012][HNOI2015]开店(动态点分治,树链剖分)

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

  7. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

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

  8. 【BZOJ4012】[HNOI2015]开店 动态树分治+二分

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

  9. [HNOI2015]开店 树链剖分,主席树

    [HNOI2015]开店 LG传送门 蒟蒻表示不会动态淀粉质. 先把点按年龄排序, 设\(dis[i]\)表示\(i\)到根的距离. 把我们要算的东西稍微变下形:\(ans\) \[ = \sum \ ...

随机推荐

  1. JavaWeb项目中各个文件夹的作用

    /WEB-INF/web.xml Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则. /WEB-INF/classes/ 包含了站点所有用的 class 文件,包括 se ...

  2. iOS之ShareSDK各社交平台申请AppKey的网址及申请流程汇总

    平台 开放平台地址 APPkey 申请流程 新浪微博 http://open.weibo.com http://bbs.mob.com/thread-89-1-4.html 新浪微博开放平台接入tip ...

  3. Webpack4 学习笔记七 跨域服务代理

    webpack 小插件使用 webpack 监听文件变化配置 webpack 处理跨域问题 Webpack 小插件使用 clean-webpack-plugin: 用于在生成之前删除生成文件夹的Web ...

  4. Angularjs基础(八)

    AngularJS Bootstrap AngularJS 的首选样式表是 Twitter Bootstrap ,Twitter Bootstrap 是目前最受欢迎的前端框架 Bootstrap 你可 ...

  5. Plupload+easyui+springmvc实现批量上传

    demo下载(java项目):http://pan.baidu.com/s/1ntmoGEd 可兼容所有常用浏览器,当前版本为V1.5.4,如果不兼容,肯定是你没有调试好啊 1.jsp代码 <% ...

  6. MySQL实现序列自增

    #创建序列表 DROP TABLE IF EXISTS `sequence`; CREATE TABLE `sequence` ( `name` ) NOT NULL COMMENT '序列名称', ...

  7. /etc/fstab开机自动挂载设备配置

    第一列:设备名字(路径?) 第二列:设备挂载路径(挂载到的位置) 第三列:分区格式 第四列:文件系统参数(?) 第五列:是否自动dump备份 0   不要    1   定期    2  不定期 第六 ...

  8. 2019年第十届蓝桥杯c++A组java/c++组题解

    #include<iostream> #include<vector> using namespace std; vector <int > vec; long l ...

  9. Windows登录密码明文获取器

    软件原理:本软件根据开源工具mimikatz2.0 修改!软件能直接读取系统明文密码! 支持32位.64位系统 win xp/vista/7/8/8.1 本机win10专业版测试不能获取,虚拟机win ...

  10. 简易的vuex用法

    vuex是vue中用于管理全局状态的一个组件,用于不同组件之间的通信,下面将介绍它的简单用法 首先安装vue与vuex npm install vue npm install vuex --save ...