题解

一道我觉得和二叉树没有关系的题……

因为直接上点分就过了,虽然很慢,而且代码很长

你需要记录一个点分树,对于每个点分树的重心,记录一下上一次进行分割时树的重心以及这个重心和上一次重心所连接的点以及连接的边的距离

然后计算这个重心和所在的树到上一个重心节点路径和的前缀和,还有节点个数和

处理每棵树的节点路径前缀和和节点个数前缀和

处理的时候枚举这个点经过的每个重心,统计过重心的路径和即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 150005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef long double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N,Q,A,num[MAXN],fa[MAXN],siz[MAXN],son[MAXN],dis[MAXN];
vector<int> age[MAXN],aux[MAXN],dis_fa[MAXN],siztr[MAXN],siztr_fa[MAXN];
vector<int64> sum[MAXN],sum_fa[MAXN];
int que[MAXN],ql,qr,id[MAXN],dfn[MAXN],idx,pre[MAXN],pos[MAXN],pre_dis[MAXN]; bool vis[MAXN];
struct node {
int to,next;
int64 val;
}E[MAXN * 2]; int head[MAXN],sumE;
void add(int u,int v,int64 c) {
E[++sumE].next = head[u];
E[sumE].to = v;
E[sumE].val = c;
head[u] = sumE;
}
int CalcG(int st) {
que[ql = qr = 1] = st;
fa[st] = 0;
while(ql <= qr) {
int u = que[ql++];siz[u] = 1;son[u] = 0;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u] && !vis[v]) {
que[++qr] = v;fa[v] = u;
}
}
}
int res = que[qr];
for(int i = qr ; i >= 1 ; --i) {
int u = que[i];
if(fa[u]) {
siz[fa[u]] += siz[u];
son[fa[u]] = max(son[fa[u]],siz[u]);
}
son[u] = max(son[u],qr - siz[u]);
if(son[u] < son[res]) res = u;
}
return res;
}
void Calc(int st,int64 val) {
que[ql = qr = 1] = st;fa[st] = 0;dis[st] = val;
while(ql <= qr) {
int u = que[ql++];
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(!vis[v] && v != fa[u]) {
dis[v] = dis[u] + E[i].val;
fa[v] = u;
que[++qr] = v;
}
}
}
}
int64 S(int u,int R) {
int siz = aux[u].size();
int64 res = 0;
for(int i = 0 ; i < siz - 1; ++i) {
int z = aux[u][i],y = aux[u][i + 1];
int t = upper_bound(age[z].begin(),age[z].end(),R) - age[z].begin() - 1;
res += 1LL * (siztr[z][t] - siztr_fa[y][t]) * dis_fa[u][i] + sum[z][t] - sum_fa[y][t];
}
res += sum[u][upper_bound(age[u].begin(),age[u].end(),R) - age[u].begin() - 1];
return res;
}
bool cmp(int a,int b) {
return num[a] < num[b];
}
void dfs_G(int u,int f,int64 c) {
int G = CalcG(u);
dfn[++idx] = G;
pre[G] = f;pos[G] = u;pre_dis[G] = c;vis[G] = 1;
for(int i = head[G] ; i; i = E[i].next) {
int v = E[i].to;
if(!vis[v]) dfs_G(v,G,E[i].val);
}
}
void Init() {
read(N);read(Q);read(A);
for(int i = 1 ; i <= N ; ++i) read(num[i]); for(int i = 1 ; i < N ; ++i) {
int u,v;int64 c;
read(u);read(v);read(c);
add(u,v,c);add(v,u,c);
}
dfs_G(1,0,0);
memset(vis,0,sizeof(vis));
for(int i = 1 ; i <= idx ; ++i) {
int G = dfn[i];
if(pre[G]) {
Calc(pos[G],pre_dis[G]);
sum_fa[G].resize(sum[pre[G]].size());
siztr_fa[G].resize(sum[pre[G]].size());
for(int i = 1 ; i <= qr ; ++i) {
int u = que[i];
int t = lower_bound(age[pre[G]].begin(),age[pre[G]].end(),num[u]) - age[pre[G]].begin();
sum_fa[G][t] += dis[u];
siztr_fa[G][t]++;
}
int s = sum_fa[G].size();
for(int i = 1 ; i < s ; ++i) {sum_fa[G][i] += sum_fa[G][i - 1];siztr_fa[G][i] += siztr_fa[G][i - 1];}
}
Calc(G,0);
vis[G] = 1;
for(int i = 1 ; i <= qr ; ++i) id[i] = que[i];
sort(id + 1,id + qr + 1,cmp);
int s = 0;
sum[G].pb(0);age[G].pb(-1);siztr[G].pb(0);
for(int i = 1 ; i <= qr ; ++i) {
int u = id[i];
aux[u].pb(G);
dis_fa[u].pb(dis[u]);
if(i == 1 || num[u] != num[id[i - 1]]) {
age[G].pb(num[u]);
sum[G].pb(0);siztr[G].pb(0);++s;
}
sum[G][s] += dis[u];
siztr[G][s]++;
}
for(int i = 1 ; i <= s ; ++i) {sum[G][i] += sum[G][i - 1];siztr[G][i] += siztr[G][i - 1];}
age[G].pb(A + 1);sum[G].pb(sum[G][s]);
}
}
void Solve() {
int64 ans = 0;
int u,a,b;
for(int i = 1 ; i <= Q ; ++i) {
read(u);read(a);read(b);
a = (a + ans) % A;b = (b + ans) % A;
if(a > b) swap(a,b);
ans = S(u,b) - S(u,a - 1);
out(ans);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}

(谁来拯救一下我越写越慢越写越长的数据结构题= =)

【LOJ】#2116. 「HNOI2015」开店的更多相关文章

  1. loj #2116. 「HNOI2015」开店

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

  2. LOJ #2116 Luogu P3241「HNOI2015」开店

    好久没写数据结构了 来补一发 果然写的时候思路极其混乱.... LOJ #2116 Luogu P3241 题意 $ Q$次询问,求树上点的颜色在$ [L,R]$中的所有点到询问点的距离 强制在线 询 ...

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

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

  4. 「HNOI2015」开店(树链剖分, 主席树)

    /* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...

  5. LOJ #2135. 「ZJOI2015」幻想乡战略游戏(点分树)

    题意 给你一颗 \(n\) 个点的树,每个点的度数不超过 \(20\) ,有 \(q\) 次修改点权的操作. 需要动态维护带权重心,也就是找到一个点 \(v\) 使得 \(\displaystyle ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. CentOS安装git及使用Gitolite来管理版本库

    首先吐槽一下网上的各种教程,大部分都扯蛋,估计都是些所谓的"编辑"在网上瞎抄来的-- 以下内容都是基于CentOS的服务器端,Mac OS X的客户端. 如果是使用的Windows ...

  2. 学习4__STM32--中断

    Cortex-M处理器的NVIC接收中断请求各种源 > 从图中可看出,NVIC是一个外设中断的管理器,简化core的工作,控制着整个芯片的中断功能 > NVIC负责给外设中断分配优先级,使 ...

  3. 【uoj7】 NOI2014—购票

    http://uoj.ac/problem/7 (题目链接) 题意 给出一棵有根树,每次从一个节点出发可以买票到达它的一定范围内的祖先.问对于每一个点,到达根的最小花费是多少. Solution 右转 ...

  4. c# 16进制byte转成int

    ]; Ratedata=System.BitConverter.GetBytes(FreResultTBoxValue); 上面这个 FreResultTBoxValue 变量是int,系统中自带in ...

  5. (转)丢掉鼠标吧,使用最好用的eclipse快捷键

    背景:eclipse作为自己经常使用的一款开发工具,熟练运用,能够达到事半功倍的效果.下面这篇文章总结了一些平时经常要使用的快捷键,十分的方便. 介绍Eclipse快捷键的文章很多,但大多都不详细,且 ...

  6. vue-devtools/安装vue-devtools

    一.在github上下载压缩包,github下载地址:https://github.com/vuejs/vue-devtools 二.解压到本地的某盘 三.用你的npm中进入该文件夹下 在npm中执行 ...

  7. error while loading shared libraries: libmysqlcppconn.so.7: cannot open shared object file: No such file or directory

    1. 即使libmysqlcppconn.so.7和与之相关存在,也报这个错误. 解决方法:临时添加LD_LIBRARY_PATH, 假使 libmysqlcppconn.so在/usr/local/ ...

  8. debian及ubuntu挂载本地硬盘的ISO镜像文件

    1.定位Debian ISO镜像的位置,比如说sda3 fdisk -l 2.挂载: # mount -t auto /dev/sda3 /media/mnt 生成isodebian路径 /mnt# ...

  9. Qt ------ WAV 音频文件播放

    1.用 QFile 打开 WAV 文件,读出文件头信息,看看是否符合音频播放设备的要求 QAudioDeviceInfo m_audioOutputDevice;//可以获取音频输出设备的信息,比如哪 ...

  10. OpenStack 云主机深入了解(十四)

    云主机深入了解 1.云主机在计算节点以进程方式运行 2.监听vnc的端口,vnc默认端口从5900开始, 多台云主机,端口递增 3.云主机桥接网卡,与宿主机联通网络 提示:在openstack环境下, ...