• 【离线/并查集】CF1213 G


    想起来好久没写题解了,随便写一下把

    感觉写多了div3后面的题就变得简单了,div3似乎没什么思维含量,甚至有时候能开出div3的2100....

     心血来潮写一下这个*1800的题解,思路一下就出了,但是一开始多了个log被卡了,提醒一下自己

    Problem - G - Codeforces

    题意:

     

    思路:

    首先做法肯定要给询问排序,那就相当于离线

    离线的写法还是有讲究的,最好是把答案全部求出来再去O(1)查询,不然容易被卡

    排序之后枚举边的权值,就是把边一条条加上去,相当于Kruskal的过程了

    问题是点对的贡献怎么算,很显然可以拆,对于一个连通块,贡献为sz * (sz - 1)

    那么对于每个询问是不是都要考虑遍历所有连通块,但是这样是O(nq)的

    这个也是套路了,考虑询问之间的变化量,其实就是数据结构多一格的思想

    如果加边之后两个连通块变成一个了,贡献的变化量是什么呢,这个可以手推

    之前是 x * (x - 1) / 2,y * (y - 1) / 2

    之后是 (x + y) * (x + y - 1) / 2

    减一减就是 x * y

    那么在合并之后贡献 += x * y即可

    一开始我写成这样

    1. #include
    2. #define int long long
    3. constexpr int N = 2e5 + 10;
    4. constexpr int M = 2e5 + 10;
    5. constexpr int mod = 1e9 + 7;
    6. constexpr int Inf = 0x3f3f3f3f;
    7. std::pair<int, int> q[N];
    8. std::vectorint, 2> > E[N];
    9. int n, m;
    10. int b[N];
    11. int f[N], sz[N];
    12. int find(int x) {
    13. return f[x] = (x == f[x]) ? x : find(f[x]);
    14. }
    15. void join(int u, int v) {
    16. int f1 = find(u), f2 = find(v);
    17. if (sz[f1] > sz[f2]) std::swap(f1, f2);
    18. if (f1 != f2) {
    19. f[f1] = f2;
    20. sz[f2] += sz[f1];
    21. }
    22. }
    23. void solve() {
    24. std::cin >> n >> m;
    25. for (int i = 1; i <= n; i ++) {
    26. f[i] = i;
    27. sz[i] = 1;
    28. }
    29. for (int i = 1; i <= n - 1; i ++) {
    30. int u, v, w;
    31. std::cin >> u >> v >> w;
    32. E[w].push_back({u, v});
    33. }
    34. for (int i = 1; i <= m; i ++) {
    35. std::cin >> q[i].first;
    36. q[i].second = i;
    37. }
    38. std::sort(q + 1, q + 1 + m);
    39. int ans = 0;
    40. for (int i = 1; i <= m; i ++) {
    41. int w = q[i].first;
    42. for (auto [u, v] : E[w]) {
    43. int f1 = find(u), f2 = find(v);
    44. if (f1 != f2) {
    45. ans += sz[f1] * sz[f2];
    46. }
    47. join(u, v);
    48. }
    49. b[q[i].second] = ans;
    50. }
    51. for (int i = 1; i <= m; i ++) {
    52. std::cout << b[i] << " \n" [i == m];
    53. }
    54. }
    55. signed main() {
    56. std::ios::sync_with_stdio(false);
    57. std::cin.tie(nullptr);
    58. int t = 1;
    59. while(t --) {
    60. solve();
    61. }
    62. return 0;
    63. }

    这样子 T7了,但是枚举权值就没问题,不知道为什么这样会快,可能是STL的问题....

    以后离线就写成把所有答案都求出来再去O(1)查询的形式会好一点,不容易被卡....

    1. #include
    2. #define int long long
    3. constexpr int N = 2e5 + 10;
    4. constexpr int M = 2e5 + 10;
    5. constexpr int mod = 1e9 + 7;
    6. constexpr int Inf = 0x3f3f3f3f;
    7. std::vectorint, 2> > E[N];
    8. int n, m;
    9. int b[N];
    10. int f[N], sz[N];
    11. int find(int x) {
    12. return f[x] = (x == f[x]) ? x : find(f[x]);
    13. }
    14. void join(int u, int v) {
    15. int f1 = find(u), f2 = find(v);
    16. if (sz[f1] > sz[f2]) std::swap(f1, f2);
    17. if (f1 != f2) {
    18. f[f1] = f2;
    19. sz[f2] += sz[f1];
    20. }
    21. }
    22. void solve() {
    23. std::cin >> n >> m;
    24. for (int i = 1; i <= n; i ++) {
    25. f[i] = i;
    26. sz[i] = 1;
    27. }
    28. for (int i = 1; i <= n - 1; i ++) {
    29. int u, v, w;
    30. std::cin >> u >> v >> w;
    31. E[w].push_back({u, v});
    32. }
    33. int ans = 0;
    34. for (int w = 1; w <= 2e5; w ++) {
    35. for (auto [u, v] : E[w]) {
    36. int f1 = find(u), f2 = find(v);
    37. if (f1 != f2) {
    38. ans += sz[f1] * sz[f2];
    39. }
    40. join(u, v);
    41. }
    42. b[w] = ans;
    43. }
    44. int q = 1;
    45. for (int i = 1; i <= m; i ++) {
    46. std::cin >> q;
    47. std::cout << b[q] << " \n" [i == m];
    48. }
    49. }
    50. signed main() {
    51. std::ios::sync_with_stdio(false);
    52. std::cin.tie(nullptr);
    53. int t = 1;
    54. while(t --) {
    55. solve();
    56. }
    57. return 0;
    58. }

  • 相关阅读:
    TI/德州仪器 TPD13S523RSVR HDMI 13 通道 ESD保护解决方案
    论文阅读 Dynamic Network Embedding by Modeling Triadic Closure Process
    OpenMesh 网格面片随机赋色
    css如何将border线加到元素内部,占内边距,不占外边距
    【C语言数据结构】图-邻接矩阵法
    Web服务器的搭建
    day22-web开发会话技术04
    TypeScript深度掌握
    2020 CCPC Changchun F. Strange Memory【dsu on tree】
    操作系统对设备的管理:I/O软件的结构层次
  • 原文地址:https://blog.csdn.net/weixin_62528401/article/details/133937479