题目链接: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. LeetCode1.两数之和 JavaScript

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 实例: 给定 nums = [2, 7, 11, 15], target ...

  2. Oracle 手工创建awr快照,获取报告

    Oracle 的自动化工具都是通过后台的进程调用相关的函数实现,而Oracle也允许用户通过包来手工调用这些函数,显然这样增加了工具的安全性,也提高了可操作性,使得DBA可以更灵活的使用这些函数来满足 ...

  3. 2018 Wannafly summer camp Day8--区间权值

    区间权值 小Bo有\(n\)个正整数\(a_1\)--\(a_n\),以及一个权值序列\(w_1\)--\(w_n\),现在她定义\(f(l,r)=(\sum_{i=l}^r a_i^2) *w_{r ...

  4. docker搭建基于percona-xtradb-cluster方案的mysql集群

    一.部署环境 序号 hostname ip 备注 1 manager107 10.0.3.107 centos7;3.10.0-957.1.3.el7.x86_64 2 worker68 10.0.3 ...

  5. JavaSE库存管理系统项目实战

    需求分析 企业库房用于存放成品.半成品.原材料.工具等物资,一般情况下,这些物资统称为物料.库存管理常见业务包括物资的入库.出库.盘点.退货.报废以及财务核算等,业务逻辑比较复杂,库房信息系统项目开发 ...

  6. scrapy框架爬取笔趣阁完整版

    继续上一篇,这一次的爬取了小说内容 pipelines.py import csv class ScrapytestPipeline(object): # 爬虫文件中提取数据的方法每yield一次it ...

  7. 常用 css html 样式

    CSS基础必学列表 CSS width宽度 CSS height高度 CSS border边框 CSS background背景 CSS sprites背景拼合 CSS float浮动 CSS mar ...

  8. C# FTP上传文件时出现"应 PASV 命令的请求,服务器返回了一个与 FTP 连接地址不同的地址。"的错误

    FTP上传文件时出现"应 PASV 命令的请求,服务器返回了一个与 FTP 连接地址不同的地址."的错误 解决方法是在原代码上增加这句话 reqFTP.UsePassive = f ...

  9. Go语言中的HTTP

    Go中的http使用 package main import ( "fmt" "net/http" "io/ioutil" "st ...

  10. AES128加密-S盒和逆S盒构造推导及代码实现

    文档引用了<密码编码学与网络安全--原理和实践>里边的推导过程,如有不妥,请与我联系修改. 文档<FIPS 197>高级加密标准AES,里边有个S盒构造,涉及到了数论和有限域的 ...