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

*题解:P3521 [POI 2011] ROT-Tree Rotations

原题链接

解析

首先观察到,对于一个以 \(x\) 为根的子树,左右子树内部叶子的排列顺序不会影响最终是否要在 \(x\) 点进行交换操作。也就是说,可以把求以左/右子树的答案看作是一个子问题。现在假设我们已经处理完了左右子树,接下来判断是否要交换左右子树。对于不交换的情况,贡献为 \(\sum_{x\in L}\sum_{y\in R}[x>y]\),其中 \(L,R\) 分别为左右子树的叶子权值集合。同理可得交换情况的贡献。对于内层的求和,考虑使用权值线段树优化掉,这样左右两棵子树各有一棵权值线段树,对于外层的求和,可以在合并的时候处理,具体地:

设当前权值线段树结点为 \(p\),管辖区间为 \([l,r]\),左右子树对应的权值线段树分别为 \(T_l,T_r\)

  • 对于 \(T_l\) 中有,但在 \(T_r\) 中没有的结点 \(p\),在此处统计 \(T_r\)\([r + 1,n]\) 中的元素个数,将其与 \(T_l\)\([l,r]\) 中的元素个数相乘。
  • 对于两子树均有的满足 \(l=r\) 的结点 \(p\),在此处统计 \(T_r\)\([r + 1,n]\) 中的元素个数。

时间复杂度 \(O(n \log^2 n)\)

然而,此题的空间限制为 64 MiB,统计时的查询操作会使得我们要开的点数乘以二从而 MLE(虽然由于洛谷的空间计算机制,使用此种做法仍然可以通过本题)。

想要抛弃查询函数,其实只需换个地方查询。对于当前权值区间 \([l,r]\),将左半边和右半边划分为子问题,那么就只需要统计横跨左右两边的逆序对了,其数量即为 \(T_l\)\([l,mid]\) 中的元素个数乘上 \(T_r\)\([mid + 1,r]\) 中的元素个数。

时间复杂度 \(O(n \log n)\)

代码

/*
*/
#include <bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) ((x) << 1 | 1)
#define mid (l + r >> 1)
using namespace std;
const int N = 2e5 + 5,M = 19;
typedef long long ll;
typedef pair<int,int> pii;
int tl[N << 2],tr[N << 2],ls[N * M],rs[N * M],rt[N << 2],cnt = 1,siz,val[N << 2];
int t[N * M];
ll res; 
void read(int x,int f){int l,r;cin>>l;cnt++;tl[x] = cnt; if(!l){read(cnt,x);}else{val[cnt] = l;}cin>>r;cnt++;tr[x] = cnt;if(!r){read(cnt,x);}else{val[cnt] = r;}
}
void push_up(int p){t[p] = t[ls[p]] + t[rs[p]];
}
void add(int &p,int l,int r,int k,int x){if(l > k || r < k) return;if(!p) p = ++siz;if(l == r){t[p] += x;return;}add(ls[p],l,mid,k,x),add(rs[p],mid + 1,r,k,x);push_up(p);
}
ll c1,c2;
int merge(int &x,int &y,int l,int r){c1 += 1ll * t[ls[x]] * t[rs[y]];c2 += 1ll * t[rs[x]] * t[ls[y]];if(!x || !y){return max(x,y);}if(l == r){t[x] += t[y];return x; }ls[x] = merge(ls[x],ls[y],l,mid);rs[x] = merge(rs[x],rs[y],mid + 1,r);push_up(x);return x;
} 
void sol(int x){if(!x) return;if(!tl[x]){add(rt[x],1,N - 1,val[x],1);return; }sol(tl[x]),sol(tr[x]);c1 = 0,c2 = 0;rt[x] = merge(rt[tl[x]],rt[tr[x]],1,N - 1);res += min(c1,c2);
} 
int main(){ios::sync_with_stdio(false);cin.tie(0);
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);int n;cin>>n;int x;cin>>x;if(n == 1){cout<<0;return 0;}read(1,0);sol(1);cout<<res;return 0;
}
http://www.jsqmd.com/news/705493/

相关文章:

  • 红牌作战的实施方法:详解红牌作战的实施方法与整改流程
  • 有关java中string源码和它的一些方法
  • WarcraftHelper魔兽争霸3优化插件:现代系统完美兼容终极方案
  • Docker AI Toolkit 2026安全配置黄金清单(2026年CIS Benchmark官方对标版)
  • 去重 DISTINCT、别名 AS
  • 异步编程CompletableFuture的那些方法allOf,anyOf
  • 2026最权威的六大降重复率工具横评
  • RabbitMQ学习2 RabbitMQ-Java客户端
  • 西恩士高端显微检测 液冷冷板清洁度显微镜分析 - 工业干货社
  • return 结果1, 结果2 在python中和在javascript中的区别
  • 【微服务与云原生架构】DevOps、CI/CD流水线、GitOps 系统性知识体系
  • YetAnotherKeyDisplayer完整指南:3大场景实战与5个深度定制技巧
  • 华硕笔记本终极优化指南:用G-Helper一键解决性能与色彩问题![特殊字符]
  • 开源金融研究智能体Dexter:基于AI的自动化投资分析实践
  • 制作加笔记
  • 量子Kerr非线性谐振器在机器学习核方法中的应用
  • WaveTools:为《鸣潮》玩家打造的全能游戏优化伴侣
  • Python零基础入门学习之输入与输出
  • 矩阵分解在推荐系统中的应用与实践
  • python click
  • 碳交易与需求响应双轮驱动的综合能源系统优化运行软件
  • 2026年3月可靠的上海钢结构厂家推荐,钢结构板房/设备钢平台/工业钢平台/仓库钢平台,上海钢结构生产厂家有哪些 - 品牌推荐师
  • python常见运算符及用法小结
  • 别留小尾巴/尽快剪掉小尾巴:从一次“ABA”字段重命名,谈谈“解决问题要彻底”
  • LocalGPT:本地化AI助手与3D生成器的架构解析与实践指南
  • MS2130芯片HDMI采集棒性能解析与应用指南
  • Hermes Agent 为什么最近总被反复提起?
  • IPXWrapper终极指南:让Windows 11完美运行90年代经典游戏联机
  • 液冷冷板清洁度颗粒测试设备 西恩士液冷设备优选厂商 - 工业干货社
  • VS Code MCP插件开发实战:手把手完成服务注册、工具发现、会话路由全流程(附GitHub可运行模板)