题目链接: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. data-ng-hide 指令

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  2. JS JavaScript中的this

    this是JavaScript语言中的一个关键字 它是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用. function test() { this.x = 1; } 上面代码中,函 ...

  3. c# 开发可替换的通用序列化库

    开篇继续吹牛.... 其实没有什么可吹的了,哈哈哈哈哈 主要是写一个通用库,既可以直接用,又方便替换,我的序列化都是采用第三方的哈. 我不上完整代码了,只是给大家讲讲过程. 1.写一个序列化的类,我是 ...

  4. mix-blend-mode 混合模式 background-blend-mode 背景混合模式 isolation:isolate 隔离

    css3 mix-blend-mode 混合模式 该属性不仅可以作用于HTML,还可以作用于SVG 兼容性: IE 8~11 Edge 12~14 Firefox 41~47 chrome 45~51 ...

  5. 『嗨威说』常见的C++函数模板整理(一)

    开学两天,身上的职责直接变为两个班班长,三个小组组长,哇这事情估计够我忙活了,想躲都躲不掉啊,看来我还是真招人推荐各种管理职务啊,以后要是有人推荐我当经理啊领导啊该多好哈哈哈哈.记得今天奶奶生日,很开 ...

  6. 【C语言】素数判定

    题目:素数判定. 编写函数,参数是一个正整数n,如果它是素数,返回1,否则返回0. 分析 质数概念: 质数:除了1之外,只能被它本身整除的正数称为质数 如果这个数能被其他正数整除,说明这个数有两个或以 ...

  7. .scripts/mysql_install_db: 没有那个文件或目录

    .scripts/mysql_install_db: 没有那个文件或目录 查了好多地方,在书上找到了解决方案,太不容易了 原因与解决方法: 系统与MYSQL版本不同,系统64位使用64位MYSQL,3 ...

  8. 三、css篇

    #这里强烈推荐一本书<css世界>,css第一书. #上面的层叠顺序得记住. 1.align-items  justify-content 是flex(弹性盒模型)必须要会的属性,alig ...

  9. Linux Shell常用命令(长期更新)

    #判断某个字段是否匹配指定值 awk -F"," '{if($4=="value"){print $1} else {print $0}}' file.txt ...

  10. Mysql导出表结构和数据

    导出数据库 -- 导出dbname表结构 mysqldump -uroot -p123456 -d dbname > dbname.sql -- 导出dbname表数据 mysqldump -u ...