当前位置: 首页 > news >正文

P3241 [HNOI2015] 开店

为啥都是点分树大神。

我们考虑先按照 \(a\) 排序,然后分块。我们先对于每一个块开一个数组预处理出这块中的点对树中的每一个点的具体距离贡献之和。那么由距离公式,设 \(l(u,v)\) 表示最近公共祖先,\(d_u\) 表示 \(u\)\(1\) 的距离之和,那么对于答案 \(u\) 和块中点的集合 \(S\),拆成

\[|S|d_u+\sum_{v\in S}d_v-2\sum_{v\in S}d_{l(u,v)} \]

关键在于我们如何维护最后那个。考虑枚举最近公共祖先 \(x\),那么发现它会对它的子树 \(T_v\) 贡献 \(N_x-N_v\) 个值,其中 \(N_x\)\(x\) 子树中有多少个 \(S\) 中的值。

之后就是散块枚举用预处理 \(O(1)\) 求最近公共祖先做到 \(O(B)\)。那么时间复杂度就是 \(O(\frac{n^2}{B}+q(B+\frac{n}{B}))\),取 \(B=\sqrt{n}\) 平衡到 \(O(n\sqrt{n})\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
typedef long long ll;
const int MAXN=1.5e5+5;
const int B=400;
int n,Q,A;
pair<int,int>a[MAXN];
vector<pair<int,int>>adj[MAXN];
int st[MAXN][20],dfn[MAXN],dfntot,dep[MAXN],lg[MAXN],xl[MAXN];void init(int u,int f){dfn[u]=++dfntot;xl[dfntot]=u;st[dfntot][0]=f;for(auto eg:adj[u]){int v=eg.first,w=eg.second;if(v==f){continue;}dep[v]=dep[u]+w;init(v,u);}    
}
#define gin(u,v) (dfn[u]<dfn[v]?u:v)
int lca(int u,int v){if(u==v){return u;}u=dfn[u],v=dfn[v];if(u>v){swap(u,v);}u++;int g=lg[v-u+1];return gin(st[u][g],st[v-(1<<g)+1][g]);
}
int sz[MAXN];
bool gd[MAXN];
ll dd[MAXN];
struct Kuai{int l,r;ll nm[MAXN];void init(){ll v=0;rep(i,l,r){v+=dep[a[i].second];gd[a[i].second]=true;}rep(i,1,n){nm[i]=v+1ll*(r-l+1)*dep[i];dd[i]=0;}for(int j=n;j>=1;--j){int u=xl[j];sz[u]=gd[u];for(auto eg:adj[u]){if(eg.first==st[j][0]){continue;}sz[u]+=sz[eg.first];}}rep(j,1,n){int u=xl[j];nm[u]-=(dd[u]+2ll*dep[u]*sz[u]);for(auto eg:adj[u]){if(eg.first==st[j][0]){continue;}dd[eg.first]=dd[u]+2ll*dep[u]*(sz[u]-sz[eg.first]);}}rep(i,l,r){gd[a[i].second]=false;}}
}k[MAXN/B+10];
ll la;
int id[MAXN];
ll ks(int l,int r,int u){ll ans=0;rep(j,l,r){int v=a[j].second;ans+=dep[u]+dep[v]-2*dep[lca(u,v)];}return ans;
}
pair<int,int>ga(int l,int r){return {min((la+l)%A,(la+r)%A),max((la+l)%A,(la+r)%A)};
}
int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>Q>>A;rep(i,1,n){cin>>a[i].first;a[i].second=i;}rep(i,1,n-1){int u,v,w;cin>>u>>v>>w;adj[u].push_back({v,w});adj[v].push_back({u,w});}sort(a+1,a+n+1);int nb=(n+B-1)/B;rep(i,1,nb){k[i].l=k[i-1].r+1;k[i].r=k[i].l+B-1;}k[nb].r=n;rep(i,2,n){lg[i]=lg[i>>1]+1;}init(1,0);rep(j,1,lg[n]){rep(i,1,n-(1<<j)+1){st[i][j]=gin(st[i][j-1],st[i+(1<<(j-1))][j-1]);}}rep(i,1,nb){k[i].init();rep(j,k[i].l,k[i].r){id[j]=i;}}rep(qq,1,Q){int l,r,u;cin>>u>>l>>r;pair<int,int>lx=ga(l,r);l=lx.first,r=lx.second;l=lower_bound(a+1,a+n+1,make_pair(l,0))-a,r=upper_bound(a+1,a+n+1,make_pair(r,n+1))-a-1;ll ans=0;if(id[l]==id[r]){ans=ks(l,r,u);}else{ans=ks(l,k[id[l]].r,u)+ks(k[id[r]].l,r,u);rep(i,id[l]+1,id[r]-1){ans+=k[i].nm[u];}}cout<<ans<<"\n";la=ans;}return 0;
}
http://www.jsqmd.com/news/139996/

相关文章:

  • Shell 脚本
  • 不懂技术怕什么?陀螺匠低代码平台,拖拽之间搞定复杂数据关联
  • 夸克网盘不限速_在线公益解析站
  • 同步通信协议(I2C/SPI)驱动OLED/EEPROM/传感器实战
  • Chat2PDF 的最神级用法,其实是一键把 AI 对话变成干净高保真的 PDF - 实践
  • CRMEB 标准版系统(PHP)- 前端多语言开发指南
  • 午餐肉灌装机市场风向标:优质午餐肉生产厂家大公开,行业内评价好的灌装机公司博锐层层把关品质优 - 品牌推荐师
  • 高速斩拌机品牌权威测评,谁是行业真王者?搅拌机源头厂家精选实力品牌榜单发布 - 品牌推荐师
  • 当“同时发生”成为攻击武器
  • 学习《Transformer原理》读书报告
  • OriginPro 2024 保姆级下载安装教程图文详细步骤(附激活激活 + 中文切换,亲测有效)
  • 跨数据源搜索的优化过程
  • 学长亲荐8个AI论文工具,本科生轻松搞定论文格式!
  • 三星自研GPU剑指AI芯片霸权,2027年能否撼动英伟达?
  • 高速斩拌机厂家综合实力排行,国内有实力的搅拌机品牌怎么选择博锐满足多元需求 - 品牌推荐师
  • 学生管理系统!
  • 当CAIE证书遇上职场现实:考后的路该怎么走?
  • 天气查询前端
  • 天气查询前端
  • DeepAnaX「GEO优化分析统计系统」重磅升级:让每一份数据都通往清晰决策
  • MySQL 日志体系总览
  • 在postgresql和duckdb的多表连接中其中一个表引用另一个表的数据
  • 2025最新!研究生必备8个AI论文工具:开题报告与文献综述全测评
  • 快递查询前端
  • 同步通信协议(I2C协议、SPI协议、驱动OLED/EEPROM/传感器)教程,文章内容利于搜索引擎搜索,整篇文章不要有AI生成痕迹
  • 2025必备10个降AIGC工具,MBA人必看!
  • 博客导引 - 少年
  • “榜单制造者”与“价值布道者”:GEO讲师的两极分化
  • 怎么渡过骑行倦怠期?
  • 学长亲荐10个AI论文平台,自考毕业论文轻松搞定!