题解:AT_arc138_f [ARC138F] KD Tree

news/2025/10/10 20:33:56/文章来源:https://www.cnblogs.com/LUlululu1616/p/19133810

题意:平面上有 \(n\) 个点 \((i,p_i)\)\(p\) 是一个排列。每次操作可以选择 \(x/y\) 和一个坐标,将点列分成左右/上下两边(保持两边的相对顺序不变),分别递归下去,直到只剩下一个点,把它加入答案序列末尾。求最终能生成多少种不同的答案序列。

做法:

首先很自然地考虑目前剩下的矩形为 \(x\in[l,r],y\in[u,d]\),记此时的答案为 \(f_{l,r,u, d}\)。考虑一刀劈成两半继续递归,但是显然这样直接算是错的,考虑如下情况:

  • 只有 \((1,1),(2,2)\) 两个点。

此时你做对 \(x\) 轴和 \(y\) 轴的操作是没有区别的。

那么对于这种会重复的我们一般考虑加一些限制使他不会重复。这里我们先定义一些东西,考虑现在这个区域中剩下了 \(k+1\) 个点,离散后应该会剩下 \(x_1<x_2<\cdots <x_k\)\(y_1<y2<\cdots <y_k\) 这些 切割线是有用的。我们考虑这么定义一个操作的字典序,按字典序从小到大排是 \(x_1,y_1,x_2,y_2,\cdots,x_k,y_k\)。这样排有什么好处呢?按字典序我们就可以让一种答案序列对应唯一一种操作序列,同时交错排布会有利于我们之后的分讨。

考虑如果一个操作序列第一刀切在的 \(x_i\) 这个位置,我们先算出来切在这里的总方案数,为 \(f_{l,x_i,u,d}\times f_{x_i+1, r,u,d}\)。但是有可能有操作序列字典序更小的得到了这个答案序列,考虑是 \(x_j\) 还是 \(y_j\)

  • \(x_j(j<i)\) 得到。

画图,那么应该分为这么几块:

那么形如 ABC 这样的操作序列就会被 \(x_j\) 解决而不是 \(x_i\),三部分方案乘起来即可。

  • \(y_j (j<i)\) 得到。

这样会分成四块:

考虑 \(x_i,y_j\) 分别切出来的顺序会是怎样,\(x_i\) 会是 (AB)(DC),\(y_j\) 会是 (AD)(BC)。考虑什么时候会重复计算,发现只能是 \(D\) 为空的时候我们才会记重,所以就必须得满足 \(D\) 为空才会减去。

\(y\) 的同样讨论,读者可以自己推一下。

到这里已经可以写了,只不过写起来需要分讨很多。我们这里其实会发现一个事情,就是假设我们 \(x\in[l,r],y\in[u,d]\) 的矩形包含了集合为 \(S\) 的点,那么令 \(Tx_i\) 代表 \(x_i\) 下方切出来的部分,\(Ty\) 类似定义,那么我们考虑按照字典序扫描,那么只有前面的是后面的子集的时候才会被重复统计,其实感觉也是比较显然的。那么这样就可以比较方便地实现了。因为这些集合都是矩形交出来的,所以其实只有 \(O(n^4)\) 个,不用担心状态过多。

总复杂度 \(O(n^6)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 35, mod = 1e9 + 7;
int n, p[maxn], q[maxn];
map<int, int> mp;
int popcnt(int x) {int cnt = 0;while(x)cnt += x % 2, x >>= 1;return cnt;
}
int cnt = 0;
int cal(int s) {if(popcnt(s) <= 1)return mp[s] = 1;if(mp.count(s))return mp[s];
//	cnt++;
//	if(cnt <= 10)
//		cout << s << endl;vector<int> x, y;for (int i = 1; i <= n; i++) {if((s >> i - 1) & 1)x.push_back(i), y.push_back(p[i]);} sort(y.begin(), y.end());vector<int> t;int nw1 = 0, nw2 = 0;for (int i = 0; i < x.size() - 1; i++) {nw1 |= (1 << x[i] - 1);t.push_back(nw1);nw2 |= (1 << q[y[i]] - 1);t.push_back(nw2);//	if(cnt <= 5);//		cout << s << " " << nw1 << " " << nw2 << endl;}vector<int> dp; dp.resize(t.size());int ans = 0;for (int i = 0; i < t.size(); i++) {dp[i] = cal(t[i]);for (int j = 0; j < i; j++)if((t[i] & t[j]) == t[j])dp[i] = (dp[i] - dp[j] * cal(t[i] ^ t[j]) % mod + mod) % mod;ans += dp[i] * cal(s ^ t[i]) % mod; ans %= mod;}
//	cout << s << " " << ans << endl;return mp[s] = ans;
}
signed main() {cin >> n;for (int i = 1; i <= n; i++)cin >> p[i], q[p[i]] = i;cout << cal((1 << n) - 1) << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/934389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SP33 TRIP - Trip 个人题解

题目链接 题目大意: 给出两个字符串,要求求出所有 LCS (最长公共子序列问题)的具体方案,并按字典序输出 解题方法: 首先我们要清楚求 LCS 的长度的方法,按照闫氏DP分析法我们得到一下过程:但是我们如果直接在此…

经营不是老板一个人的事 - 智慧园区

很多企业都陷入了“高层定目标,中层传口号,基层盲执行”的怪圈。一提到“经营”,大家就会想到董事长、总经理,觉得那是高层的事。但真相是:如果经营思维只停留在高层,企业正在走向危险边缘。一、经营到底是什么?…

Codeforces Round 1051 (Div. 2)[A ~E]

―僕は其れに縋る事さえ/出来無かった訳ですから目录Codeforces Round 1051 (Div. 2)A. All Lengths SubtractionB. DiscountsC. Max TreeD. Inversion Graph Coloring Easy Version/Hard VersionE. Make Good Codefo…

如何在 Spring Boot 应用中配置多个 Spring AI 的 LLM 客户端

1. 概述 越来越多的现代应用开始集成大型语言模型(LLM),以构建更智能的功能。如何使用Spring AI快速整合LLM能力到自己的Spring Boot应用,在之前的博文中有过很多篇关于使用Spring AI使用不同供应商LLM的整合案例。…

【Azure APIM】解答REST API实现禁用自签名证书的证书链验证中的backends参数值从那里取值的问题?

问题描述 使用APIM服务时候,因为后端的API需要使用自签名证书进行验证。如果通过浏览器直接访问后端API返回正常,但是APIM请求的时候返回为500报错。 在开启Trace后,发现报错信息为:error message :The underlyin…

2025 AI 进化图谱:技术突破、场景落地与产业重构 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

题解:P14065 [PO Final 2022] 对弈 / Laserschack

题目传送门 先警示后人: 我在看题目的时候看成了 \(1 \le r,c \le 4000\) 然后被迫想了一个 \(\operatorname{O}(\operatorname{RC} \ \operatorname{log} \ \operatorname{RC})\) 发现好像有点玄 最后乱加一堆优化跑…

[Git] 放弃暂存区的修改

1 需求描述在使用 Git 进行版本控制时,有时我们会在暂存区(staging area)中暂存了一些修改,但后来发现这些修改是不需要的,想要放弃这些修改并恢复到上一次提交的状态。Git 提供了几种方法来实现这一操作。2 解决…

前端里面transform和transition 属性的区别

transform 和 transition 都是用于在 HTML 中控制元素的视觉效果和动画的 CSS 属性,但它们的作用和功能不同。下面详细解释这两个属性的区别: 1. transform 属性 transform 属性允许你对元素进行 2D 或 3D 转换(即对…

【MAC环境】安装多个 JDK - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF2064E Mycraft Sand Sort

Sol 首先 \(c\) 不能变,否则第一列就会改变。 然后注意到 \(i,j(i<j)\) 能交换当且仅当满足以下任意一条:\(\displaystyle\max_{k=i+1}^{j-1}a_k<\min(a_i,a_j)\) i+1=j那么考虑从小到大做,每次把小的数删除,…

使用eBPF技术保护FastAPI安全

本文详细介绍如何利用eBPF技术保护面向互联网的API安全,包括FastAPI、Flask、Django等框架。通过secimport工具实现Python代码的实时追踪、沙箱策略构建和运行时监控,有效防御远程代码执行等安全威胁。使用eBPF保护F…

项目案例作业2:对案例进行面向对象分析

学生管理系统面向对象分析报告 小组成员:李天瑞 202421336012 目录学生管理系统面向对象分析报告1. 案例中哪里体现出了封装性及其好处?封装性的体现封装性带来的好处2. 案例中的setter/getter模式与封装性什么是set…

20251010周五日记

20251010周五日记今天十点多回学校了,好不容易不下雨了。没想到国庆还真加了那么多天班= = 今日: 1.早上吃完早饭收拾东西慢慢悠悠回来了,打印朋辈表多亏师哥妙手回春。准备去开学代会,说来又要翘课了。 2.中午吃了…

k8s 主节点重启后 从节点 get 异常 - 教程

k8s 主节点重启后 从节点 get 异常 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

多维索引技术优化数据湖查询性能

本文介绍了一种通过多维索引技术优化数据湖查询性能的解决方案。该技术可直接集成到现有数据湖架构中,支持跨列复杂过滤,提升查询速度最高达6倍,同时降低70%计算成本,兼容主流计算引擎无需重构数据管道。Qbeast获7…

训练笔记:博弈杂题

[7-/7] A. 黎明\(1\sim n\) 排成一个环进行约瑟夫(隔一个删一个),求有多少个时刻,被删除的数的异或和为 \(0\)。 多测 \(10^5\) 组,\(n<10^{18}\)。hint:考虑把约瑟夫的过程分解为 \(\lceil\log n\rceil\) 个…

HTML5拖放API核心功能解析

好的,我们来详细解析一下 HTML5 拖放 API 的核心功能。 HTML5 拖放 API 允许用户在浏览器中抓取一个元素,并将其拖放到另一个位置。它原生支持在浏览器标签页、甚至不同浏览器、乃至桌面应用之间拖放,是现代 Web 应…

[USACO07NOV] Telephone Wire G

dp题,做法有点套路但是一开始没想到。 设 \(dp{_i}_j\) 表示第 \(i\) 位为 \(j\) 的最小花费。 然后直接往下转移就好了。点击查看代码 #include<bits/stdc++.h> #define fir first #define sec second #define…