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

Codeforces Round 1051 (Div. 2) 补题记录

Codeforces Round 1051 (Div. 2) 补题记录

D - Inversion Graph Coloring

题目大意:

当一个序列 \(b_1, b_2, \dots, b_k\) 存在一种对每个下标 \(i\) 染上红色或蓝色的方式,使得每一对 \(i < j\)\(b_i > b_j\) 的下标 \(i, j\) 的颜色不同时,我们称这个序列是“好”的。

给定一个序列 \(a_1, a_2, \dots, a_n\),计算它“好”的子序列数量,并对 \(10^9 + 7\) 取模。

思路:

考虑什么样的子序列会被计入答案。注意到,当存在下标 \(i < j < k\)\(a_i > a_j > a_k\) 时,不存在合法的染色方案。因此题目可以转化为求最长递减子序列长度小于等于 \(2\) 的子序列个数。

接着我们考虑对于第 \(i\) 个数,会与前面已经组成的哪些子序列形成新的子序列。

  • 加入最大值 \(j \leq a_i\) 的子序列中。此时由 \(a_i\) 组成的递减子序列长度为 \(1\)

  • 加入最长递减子序列长度为 \(2\) 且末尾数值 \(k \leq a_i < j\) 的子序列中。此时,\(a_i\) 代替 \(k\) 成为最长递减子序列的最后一个元素,长度依旧为 \(2\)

根据上面的两种情况以及不选择第 \(i\) 个元素与前面元素构成子序列的情况,我们进行 \(dp\),状态转移如下:

  • 不选择 \(a_i\)\(dp[i][j][k] \leftarrow dp[i - 1][j][k];\)

  • \(j \leq a_i\)\(dp[i][a_i][k] \leftarrow dp[i - 1][j][k];\)

  • \(k \leq a_i < j\)\(dp[i][j][a_i] \leftarrow dp[i - 1][j][k].\)

时间复杂度 \(O(n^3)\) 足够通过本题的 Easy Version。

接着我们考虑如何优化 \(dp\)

注意到在转移时,存在如下关系:

\[\begin{cases} dp[i][a_i][k] = \sum_{j \leq a_i} dp[i - 1][j][k] \\ \\ dp[i][j][a_i] = \sum_{k \leq a_i} dp[i - 1][j][k] \end{cases} \]

因此可以考虑把第一维砍掉,用树状数组维护 \(dp\) 每行每列的前缀和,求出增量即可。

\(code:\)

#include <bits/stdc++.h>
using namespace std;#define endl '\n'
#define i64 long longconst int mod = 1000000007;template <typename T>
struct Fenwick {int n;std::vector<T> a;Fenwick(int n = 0) {init(n);}void init(int n) {this->n = n;a.assign(n, T());}void add(int x, T v) {for (int i = x + 1; i <= n; i += i & -i) {a[i - 1] += v;}}T sum(int x) {auto ans = T();for (int i = x; i > 0; i -= i & -i) {ans += a[i - 1];}return ans;}T rangeSum(int l, int r) {return sum(r) - sum(l);}
};void MuBai() {int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i ++ ) cin >> a[i];vector<Fenwick<i64>> row(n + 1), col(n + 1);for (int i = 0; i <= n; i ++ ) {row[i].init(n + 1);col[i].init(n + 1);}row[0].add(0, 1), col[0].add(0, 1);vector f(n + 1, vector<i64>(n + 1, 0));for (int i = 1; i <= n; i ++ ) {for (int j = 0; j <= n; j ++ ) {i64 g = col[j].sum(a[i] + 1) % mod;i64 h = (a[i] < j) ? (row[j].sum(a[i] + 1) % mod) : 0;if (g) {row[a[i]].add(j, g);col[j].add(a[i], g);f[a[i]][j] += g;if (f[a[i]][j] >= mod) f[a[i]][j] -= mod;}if (h) {row[j].add(a[i], h);col[a[i]].add(j, h);f[j][a[i]] += h;if (f[j][a[i]] >= mod) f[j][a[i]] -= mod;}}}i64 ans = 0;for (int i = 0; i <= n; i ++ ) {ans += col[i].sum(n + 1) % mod;if (ans >= mod) ans -= mod;}cout << (ans < mod ? ans : ans - mod) << endl;
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);int t; cin >> t;while (t -- ) MuBai();return 0;
}
http://www.jsqmd.com/news/53386/

相关文章:

  • 常用 trick 记录
  • Motia:未来平台
  • 移动端开发
  • 代码随想录算法训练营第四章 字符串part01
  • 用ikuai软路由提供内网NTP服务
  • US$213.75 Xhorse Key Tool Midi Basic Version Update to Advanced Version Service
  • AutoVEI Truck Explorer Locksmith 2025: 700 Tokens for Truck Programming Diagnostics
  • DC-2渗透测试 - fish666
  • AutoVEI Truck Explorer 2025 Updated: 700 Tokens Programming Diagnostic Tool for Euro/Amer Trucks
  • k8s核心组件详解
  • BLOG迁移: 从Halo + CF Tunnel 到 Hugo + github + Cloudflare page
  • JDK:Linux下载安装jdk1.8
  • 图论中的核心C++算法,包括存储结构、核心思路、速记口诀以及学习方法, 一站式上机考试学习
  • hive 中 group by 和 distinct 孰优孰劣?
  • DDD抽奖项目业务回顾
  • API设计最佳实践 - 智慧园区
  • Python高阶知识点整理
  • 第4单元检测卷
  • javascript下载文件五种方式
  • ubunutu连接蓝牙键盘鼠标
  • 详细介绍:从 1.0 到 13.0:C# 十八年进化史,一部写给开发者的语言成长记
  • 生研界:技术赋能,AI如何重塑医学科研生态?
  • 2025ICPC区域赛成都站记——为者败之,执者失之
  • quickfox windows 海外回国加速器 会导致部分国外网站不能使用
  • 4433
  • 在VMware Workstation设置虚拟机的VNC连接功能
  • rust基础第三篇:所有权
  • Houdini软件简介
  • Windows系统磁盘管理——迁移“恢复分区”
  • 2025.11.27总结