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

做题随笔:P14521

Solution

题意

原题链接

感觉题意很难形式化,建议自己读一下。

大概是:给一个定根树,每个点有一个点权,每条边有一个可通过区间,从根开始,带着一个初值向下走,每到一个点把点权加在值上,对初值 \(x\)\(q\) 个取值求可达点数量。

注意:根节点算可达点,根节点的点权也要加上。

分析

首先有一个很自然的思路:对于一个可达点 \(u\),如果初值是 \(x\),从根到 \(u\) 的路径点权和是 \(s\),到达 \(u\) 时的值就是 \(x+s\)。于是对于 \(u\) 向下的边,如果它的可通过区间是 \([l,r]\),那么可以通过这条边的初值区间就是 \([l-s,r-s]\)

好的,其实就做完了。我们直接 dfs 一次计算根到所有点的路径点权,并计算可通过区间。注意一下每个点的可达区间应对父亲取交,毕竟要先到父亲才能到它。至于统计答案,我们需要做区间加,单点查,写个差分数组就完……了吗?

注意到 \(x \in [-1 \times 10^{18},1 \times 10^{18}]\),差分数组完全开不下。但是,我们发现:每个树上的点会做两次差分数组上的操作,所以只有 \(O(n)\) 个差分数组的位是有意义的,那我们只对这些位操作就行了。相当于是:我们“离散化”了差分数组。

具体地,开一个 vector,存 \(x,d\) 表示我需要在差分数组的 \(x\) 位上执行加 \(d\) 操作。查询离线一下,对 \(x\) 排序后扫,就扫完 \(x\) 及之前的求和就行(这好像叫扫描线是吧)。

Tip:注意要扔掉 \(l>r\) 的区间,不然差分数组会错。赛时蒟蒻就是这样调了 30min。

注意下路径点权和会爆 long long,记得开 int128。

Code

#include <iostream>
#include <cctype>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <climits>typedef long long ll;ll fr() {ll x=0,f=1;char c=getchar();while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+(c^48);c=getchar();}return x*f;
}struct node{ll i;int d;bool operator< (const node &n) const&{return i<n.i;}
};std::vector<node> v;//差分数组的 vectorconst int maxn=5e5+100;struct edge{int v,nxt;ll l,r;
}e[maxn<<1];int head[maxn],tot;void ade(int u,int v,ll l,ll r) {e[++tot]={v,head[u],l,r};head[u]=tot;
}ll a[maxn];void dfs(int u,__int128_t dx,ll fl,ll fr) {dx+=a[u];for(int i = head[u]; i; i=e[i].nxt) {__int128_t l=e[i].l,r=e[i].r;l+=dx,r+=dx;l=std::max((__int128_t)-1e18-100,l),r=std::min((__int128_t)1e18+100,r);//x 的范围只有这么大,多的不用管l=std::max((ll)l,fl),r=std::min((ll)r,fr);if(l>r) continue;v.push_back({(ll)l,1});v.push_back({(ll)r+1,-1});dfs(e[i].v,dx,l,r);}
}struct qry{ll x;int id,ans;
};bool cmp1(qry q1,qry q2) {return q1.x<q2.x;
}bool cmp2(qry q1,qry q2) {return q1.id<q2.id;
}qry Q[maxn<<1];int main() {int n=fr(),q=fr();v.reserve(n<<1);for(int i = 1; i < n; i++) {int p=fr();ll l=fr(),r=fr();ade(p,i+1,l,r);}for(int i = 1; i <= n; i++) a[i]=-fr();dfs(1,0,LLONG_MIN,LLONG_MAX);std::sort(v.begin(),v.end());for(int i = 1; i <= q; i++) Q[i]={fr(),i,0};std::sort(Q+1,Q+1+q,cmp1);int now=0;int p=0;for(int i = 1; i <= q; i++) {ll x=Q[i].x;while(p<v.size()&&v[p].i<=x) {now+=v[p].d;p++;}Q[i].ans=now;}std::sort(Q+1,Q+1+q,cmp2);for(int i = 1; i <= q; i++) printf("%d\n",Q[i].ans+1);return 0;
}

一些闲话

如果觉得有用,点个赞吧!

http://www.jsqmd.com/news/42023/

相关文章:

  • 《重生之我成为世界顶级黑客》第五章:失败,失败,还是失败
  • Win11系统恢复经典的右键菜单方法(CMD快速执行)
  • 20251116
  • 智能硬件利用小聆AI自定义MCP应用开发操作讲解
  • 选拔赛题解
  • C++ 中的 **普通筛、埃氏筛、线性筛**,它们都是求质数或判断质数的方法
  • Linux - sudo -i
  • 利用单片机的TIM模块播放春日影
  • warp-cli代理
  • 完整教程:Rust语言特性深度解析:所有权、生命周期与模式匹配之我见
  • 20231427田泽航第九周预习报告
  • do文件仿真 fpga
  • 20232412 2024-2025-1 《网络与系统攻防技术》实验五实验报告
  • 本地缓存Caffeien
  • 实用指南:C++---嵌套类型(Nested Types)封装与泛型的基石
  • [ sqlite ]
  • 视野修炼-技术周刊第127期 | Valdi
  • 完整教程:机器学习:基于大数据的基金数据分析可视化系统 股票数据 金融数据 股价 Django框架 大数据技术(源码) ✅
  • 科学计算复习
  • 【AIGC】语音识别ASR:火山引擎大模型技术实践 - 详解
  • 2025年11月石笼网厂家最新推荐,聚焦资质、案例、售后的五家企业深度解读!
  • 2025 年 11 月石笼网厂家最新推荐,技术实力与市场口碑深度解析!
  • 2025年11月温州律师事务所最新推荐,实力机构深度解析与择选指南!
  • python: 用pyppeteer以无头方式抓取页面
  • python共享内存的读写同步与加锁 —— multiprocessing.Value和multiprocessing.Array、加锁
  • 2025年11月温州律师事务所最新推荐,聚焦资质、案例、服务的五家机构深度解读!
  • UI设计公司审美积累|办公类软件界面设计巧思,效率与视觉的双重升级
  • 详细介绍:AVL树手撕,超详细图文详解
  • 网络安全
  • Zhengrui 11.16 总结