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

【Codeforces】CF 2020 D

Connect the Dots

#动态规划 #并查集 #枚举

题目描述

One fine evening, Alice sat down to play the classic game “Connect the Dots”, but with a twist.

To play the game, Alice draws a straight line and marks n n n points on it, indexed from 1 1 1 to n n n. Initially, there are no arcs between the points, so they are all disjoint. After that, Alice performs m m m operations of the following type:

  • She picks three integers a i a_i ai, d i d_i di ( 1 ≤ d i ≤ 10 1 \le d_i \le 10 1di10), and k i k_i ki.
  • She selects points a i , a i + d i , a i + 2 d i , a i + 3 d i , … , a i + k i ⋅ d i a_i, a_i+d_i, a_i+2d_i, a_i+3d_i, \ldots, a_i+k_i\cdot d_i ai,ai+di,ai+2di,ai+3di,,ai+kidi and connects each pair of these points with arcs.

After performing all m m m operations, she wants to know the number of connected components † ^\dagger these points form. Please help her find this number.

† ^\dagger Two points are said to be in one connected component if there is a path between them via several (possibly zero) arcs and other points.

输入格式

Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1t105). The description of the test cases follows.

The first line of each test case contains two integers n n n and m m m ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1n2105, 1 ≤ m ≤ 2 ⋅ 1 0 5 1 \le m \le 2 \cdot 10^5 1m2105).

The i i i-th of the following m m m lines contains three integers a i a_i ai, d i d_i di, and k i k_i ki ( 1 ≤ a i ≤ a i + k i ⋅ d i ≤ n 1 \le a_i \le a_i + k_i\cdot d_i \le n 1aiai+kidin, 1 ≤ d i ≤ 10 1 \le d_i \le 10 1di10, 0 ≤ k i ≤ n 0 \le k_i \le n 0kin).

It is guaranteed that both the sum of n n n and the sum of m m m over all test cases do not exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2105.

输出格式

For each test case, output the number of connected components.

样例 #1

样例输入 #1

3
10 2
1 2 4
2 2 4
100 1
19 2 4
100 3
1 2 5
7 2 6
17 2 31

样例输出 #1

2
96
61

解法

解题思路

首先容易发现,如果以 d d d的速度经过了点 x x x,那么下次再以 d d d的速度经过这个点的时候,就可以直接跳到最后了,无需重复操作。

发现 d ≤ 10 d\leq 10 d10,因此可以直接开 d d d个并查集,来维护每个速度 d d d跳过的节点,将它们存入一个联通块内。

最后,我们还需要将同一个点的不同速度 d d d的联通块再次合并为新的联通块,这里再开一个并查集维护,最终答案就是这个并查集的联通分量了。

代码

const int N = 2e5 + 10;int fa[N][12];
int p[N];
int n, q;void init() {for (int i = 1; i <= n; ++i) {p[i] = i;for (int j = 1; j <= 10; ++j) {fa[i][j] = i;}}
}int find(int x, int y) {return fa[x][y] = fa[x][y] == x ? x : find(fa[x][y], y);
}int find(int x) {return p[x] = p[x] == x ? x : find(p[x]);
}void solve() {std::cin >> n >> q;init();int vis[12] = {};while (q--) {int x, d, k;std::cin >> x >> d >> k;vis[d] = 1;for (int i = 1; i <= k; ++i) {int u = find(x + i * d, d);int px = find(x, d), py = find(u, d);fa[px][d] = py;i = (u - x) / d; }}std::set<int>st;for (int i = 1; i <= n; ++i) {for (int j = 1; j <= 10; ++j) {if (vis[j]) {int px = find(find(i, j)), py = find(i);p[px] = py;}}}for (int i = 1; i <= n; ++i) {st.insert(find(i));}int res = st.size();std::cout << res << "\n";
}signed main() {std::ios::sync_with_stdio(0);std::cin.tie(0);std::cout.tie(0);int t = 1;std::cin >> t;while (t--) {solve();}
}

http://www.mrgr.cn/news/48516.html

相关文章:

  • plpo vue实战版教程
  • OAuth2.1的code_challenge和code_vertifier理解
  • 五子棋项目自动化测试
  • 电脑无线网wifi和有线网同时使用(内网+外网同时使用)
  • 【Linux 从基础到进阶】防止数据泄露的策略与工具
  • 【WebGIS】Cesium:天地图加载
  • 每日OJ题_牛客_比那名居的桃子_滑动窗口/前缀和_C++_Java
  • C语言—双链表
  • 科大讯飞嵌入式面试题及参考答案
  • c++ 多线程全局变量安全操作------原子操作
  • 网工内推 | 初级网工,Base北京,IE认证优先,最高14K+餐补
  • Feign的使用
  • 【专题】智启未来:新质生产力引擎驱动下的智能制造行业革新报告合集PDF分享(附原数据表)
  • 邮件营销案例成功技巧:如何打动目标客户?
  • 18063 圈中的游戏
  • 探索极简计算的新边界:从Uxn虚拟机看未来编程生态
  • 儿童画画在线支付预约报名表单在线制作小程序源码系统 带完整的安装代码包以及搭建部署教程
  • 思迅商云8四级分类
  • 哪个牌子的护眼灯防蓝光效果好?五款市场上评价较高的护眼台灯
  • xtu oj 彩球