题目链接

BZOJ4012

题解

Mychael并没有A掉,而是T掉了

讲讲主要思路

在点分树上每个点开两棵\(splay\),

平衡树\(A\)维护子树中各年龄到根的距离

平衡树\(B\)维护子树中各年龄到点分树父亲的距离

然后询问就可以在点分树上用两棵平衡树相减计算了

大常数\(O(nlog^2n)\)被卡死

// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (register int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (register int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,LL>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,LL>
#define LL long long int
#define ls ch[u][0]
#define rs ch[u][1]
#define isr(u) (fa[u] && ch[fa[u]][1] == u)
#define res register
using namespace std;
const int maxn = 200005,maxm = 10000005,INF = 1000000000;
inline int read(){
res int out = 0,flag = 1; res char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
inline void write(LL x){
if (x / 10) write(x / 10);
putchar(x % 10 + '0');
}
int Siz[maxm],siz[maxm],w[maxm],ch[maxm][2],fa[maxm],cnt;
LL Sum[maxm],sum[maxm];
struct Splay_Tree{
int rt;
void upd(int u){
Siz[u] = Siz[ls] + Siz[rs] + siz[u];
Sum[u] = Sum[ls] + Sum[rs] + sum[u];
}
void spin(int u){
int s = isr(u),f = fa[u];
fa[u] = fa[f]; if (fa[f]) ch[fa[f]][isr(f)] = u;
ch[f][s] = ch[u][s ^ 1]; if (ch[u][s ^ 1]) fa[ch[u][s ^ 1]] = f;
fa[f] = u; ch[u][s ^ 1] = f;
upd(f); upd(u);
}
void splay(int u,int f = 0){
for (; fa[u] != f; spin(u))
if (fa[fa[u]] != f) spin((isr(u) ^ isr(fa[u])) ? u : fa[u]);
if (!f) rt = u;
}
void insert(int& u,int f,int v,int Val){
if (!u){
w[u = ++cnt] = v; Sum[u] = sum[u] = Val;
fa[u] = f; siz[u] = Siz[u] = 1; splay(u);
}
else if (w[u] > v) insert(ls,u,v,Val);
else if (w[u] < v) insert(rs,u,v,Val);
else {Sum[u] += Val; sum[u] += Val; Siz[u]++; siz[u]++; splay(u);}
}
void ins(int pos,int v){insert(rt,0,pos,v);}
int pre(int u,int v){
if (!u) return 0;
if (w[u] >= v) return pre(ls,v);
else {
int t = pre(rs,v);
return t ? t : u;
}
}
int post(int u,int v){
if (!u) return 0;
if (w[u] <= v) return post(rs,v);
else {
int t = post(ls,v);
return t ? t : u;
}
}
cp query(int l,int r){
int L = pre(rt,l),R = post(rt,r);
splay(L); splay(R,L);
if (!ch[R][0]) return mp(0,0);
return mp(Siz[ch[R][0]],Sum[ch[R][0]]);
}
void init(){rt = 0; ins(-INF,0); ins(INF,0);}
}A[maxn],B[maxn];
LL ans;
int n,m,Limit,val[maxn],L,R;
int h[maxn],ne = 1;
struct EDGE{int to,nxt,w;}ed[maxn << 1];
inline void build(int u,int v,int w){
ed[++ne] = (EDGE){v,h[u],w}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v],w}; h[v] = ne;
}
LL Dis[maxn][23];
int F[maxn],Fa[maxn],size[maxn],vis[maxn],N,rt;
void getrt(int u){
F[u] = 0; size[u] = 1;
Redge(u) if (!vis[to = ed[k].to] && to != Fa[u]){
Fa[to] = u; getrt(to);
size[u] += size[to];
F[u] = max(F[u],size[to]);
}
F[u] = max(F[u],N - size[u]);
if (F[u] < F[rt]) rt = u;
}
int c[maxn],d[maxn],ci;
void dfs1(int u){
size[u] = 1; c[++ci] = u;
Redge(u) if (!vis[to = ed[k].to] && to != Fa[u]){
Fa[to] = u; d[to] = d[u] + ed[k].w;
dfs1(to);
size[u] += size[to];
}
}
int pre[maxn],dep[maxn];
void solve(int u,int D){
vis[u] = true; size[u] = 1; ci = 0; d[u] = 0; dep[u] = D;
A[u].init(); A[u].ins(val[u],0); B[u].init();
Redge(u) if (!vis[to = ed[k].to]){
Fa[to] = u; d[to] = d[u] + ed[k].w;
dfs1(to);
}
int v = pre[u];
REP(i,ci){
A[u].ins(val[c[i]],d[c[i]]);
Dis[c[i]][D] = d[c[i]];
}
if (v){
B[u].ins(val[u],Dis[u][D - 1]);
REP(i,ci) B[u].ins(val[c[i]],Dis[c[i]][D - 1]);
}
Redge(u) if (!vis[to = ed[k].to]){
N = size[to]; F[rt = 0] = INF;
getrt(to); pre[rt] = u;
solve(rt,D + 1);
}
} void work(int x){
ans = A[x].query(L,R).second;
LL dd; cp t1,t2;
for (res int u = x,i = dep[x] - 1; pre[u]; u = pre[u],i--){
dd = Dis[x][i];
t1 = A[pre[u]].query(L,R);
t2 = B[u].query(L,R);
ans += t1.second - t2.second + dd * (t1.first - t2.first);
}
printf("%lld\n",ans);
}
int main(){
n = read(); m = read(); Limit = read();
LL a,b,w;
for (res int i = 1; i <= n; i++) val[i] = read();
for (res int i = 1; i < n; i++){
a = read(); b = read(); w = read();
build(a,b,w);
}
N = n; F[rt = 0] = INF;
getrt(1);
solve(rt,0);
int u;
while (m--){
u = read(); a = read(); b = read();
L = (a + ans) % Limit;
R = (b + ans) % Limit;
if (L > R) swap(L,R);
work(u);
}
return 0;
}

BZOJ4012 [HNOI2015]开店 【动态点分治 + splay】的更多相关文章

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

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

  2. 【bzoj4012】[HNOI2015]开店 动态点分治+STL-vector

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

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

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

  4. P3241 [HNOI2015]开店 动态点分治

    \(\color{#0066ff}{ 题目描述 }\) 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱. 这样的想 ...

  5. luogu 3241 [HNOI2015]开店 动态点分治+二分+vector

    独立写出来+想出来的,1.5h就切了~ 建立点分树,然后用 $vector$ 暴力存所有子节点,然后二分一下子就可以了. #include <cstdio> #include <ve ...

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

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

  7. BZOJ4012: [HNOI2015]开店【动态点分治】

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

  8. BZOJ4012 [HNOI2015]开店 (动态点分治)

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

  9. [loj2116]「HNOI2015」开店 动态点分治

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

  10. BZOJ4012 [HNOI2015]开店

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

随机推荐

  1. Java源码解析——集合框架(三)——Vector

    Vector源码解析 首先说一下Vector和ArrayList的区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是 ...

  2. connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporarily unavailable)

    nginx + php做服务,在高并发的时候会出现一些错误  connect() to unix:/var/run/php-fpm.sock failed (11: Resource temporar ...

  3. CentOS下配置jdk

    CentOS下配置jdk 1.在jdk官网上下载最新版本的jdk 2.将jdk放到相应的位置,使用如下命令来解压. .0_181 /opt/data/ tar -zxf jdk-8u181-linux ...

  4. R语言学习笔记(十一):零碎知识点(26-30)

    26--aggregate( ) 函数aggregate()对分组中的每一个变量调用tapply()函数. aggregate(a,list,f) 第二个参数必须是列表.也就是因子部分. 第三个参数即 ...

  5. ubuntu配置机器学习环境(三) opencv 安装

    这里使用脚本安装 一些教程里使用cmake 安装,很容易出错的 使用github上的安装脚本,自动化安装 参考链接 Ubuntu $ cd Ubuntu/2.4 $ chmod +x * # 如果要安 ...

  6. 详解mysql体系结构和存储引擎

    概述 之前整理的一些mysql方面内容,适合做备忘,因为我基本不会去记这些概念性的东西,大家做个了解就可以了. 一.定义数据库和实例 1.数据库: 物理操作系统文件或其他形式文件类型的集合. 在MyS ...

  7. SQL Server 2005 导出包含(insert into)数据的SQL脚本 (使用存储过程) 分类: 数据库

    CREATE PROCEDURE dbo.UspOutputData @tablename sysname AS ) ) ) declare @xtype tinyint declare @name ...

  8. c#根据ip获取城市地址

    用的API是百度.新浪.淘宝: 1.首先是一个检测获取的值是不是中文的方法,因为有的ip只能识别出来某省,而城市名称则为空返回的json里会出现null或undefined. public stati ...

  9. 玩转Vim-札记(一)

    玩转Vim-札记(一) 简介 在这个蔚蓝色的星球上,流传着两大神器的传说:据说Emacs是神的编辑器,而Vim是编辑器之神.一些人勇敢地拾起了Vim或Emacs,却发现学习曲线陡峭而漫长,还是有一些人 ...

  10. 「个人训练」Can you solve this equation?(HDU-2199)

    题意与分析 纯粹水题.本来想做下放松心情的,结果还是被坑了qaq 重点就是在浮点误差.比较左右的下次就直接上1e-10,别看着题目说1e-4然后给个-5,结果暴wa.气傻了..... 代码 #incl ...