2019-2020 XX Open Cup, Grand Prix of Korea J. Parklife 括号序列 树上启发式合并
2019-2020 XX Open Cup, Grand Prix of Korea J. Parklife 括号序列 树上启发式合并
题意
给定x轴上的n条除端点外互不相交的带权值线段
现在可以选择一些线段 求出 任意一条线段被覆盖次数不多于i次(1≤i≤N)条件下的最大权值和
1≤N≤2500001≤Si<Ei≤1e6,1≤Vi≤1e9
分析
一般这种保证选择互不相交的条件都可以转化成树上问题 如果两个线段是包含关系转化为祖先关系,这样可以转化为类似括号序列的一棵树。问题相当于转化为树上选择一些顶点,满足任意一条链上的点不超过i个。
有比较显然的贪心:从i到i+1总是在原有基础上贪心加一些点。维护每次额外加的那些点,这可以用树形DP来做。
维护以i为根的子树的集合。显然,合并两颗子树的时候是可以直接加的(两子树对应的链独立),第k大的一定和第k的相加。这样就可以用启发式合并+优先队列实现了。
代码
const int maxn = 3e5 + 5;
struct seg{
int l,r,val;
friend bool operator < (const seg&a,const seg&b){
if(a.l == b.l) return a.r > b.r;
return a.l < b.l;
}
}a[maxn];
int n;
VI e[maxn];
VI v;
multiset<ll,greater<ll>> s[maxn];
void dfs(int u){
for(auto v:e[u]) {
dfs(v);
if(s[u].size() < s[v].size()) {
s[u].swap(s[v]);
}
multiset<ll,greater<ll>> tmp;
for(auto vv:s[v]) {
ll w = *(s[u].begin());
tmp.insert(w + vv);
s[u].erase(s[u].begin());
}
for(auto vv:tmp)
s[u].insert(vv);
}
if(u)
s[u].insert(a[u].val);
}
int main(){
n = rd();
VI ans(n + 5);
for(int i = 1;i <= n;i++)
a[i].l = rd(),a[i].r = rd(),a[i].val = rd();
a[0].l = -1e9,a[0].r =1e9;
sort(a,a + n + 1);
v.push_back(0);
for(int i = 1;i <= n;i++){
while(a[v.back()].r < a[i].r)
v.pop_back();
e[v.back()].push_back(i);
v.push_back(i);
}
dfs(0);
int p = 1;
for(auto it:s[0])
ans[p++] = it;
for(int i = 1;i <= n;i++){
ans[i] += ans[i - 1];
printf("%lld ",ans[i]);
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
2020-09-12 CodeForces-731F Video Cards 数论,分块
2020-09-12 CodeForces-232B Table 组合数学 DP