HDU-ACM 2024 Day2
T1004 a*b problem(HDU 7448)
不会。
T1005 小塔的养成游戏之梦(HDU 7449)
不会。
T1009 强攻计策(HDU 7453)
容易发现初始速度是多少对答案没有影响,所以我们默认初始速度为 \(0\)。题意相当于在平面直角坐标系上(横轴为时间,纵轴为速度),有一个目标高度,维护一条尽量接近目标的直线,但斜率只能是 \(-1/0/1\),要支持一段区间目标 \(+1\),求直线下方面积。
将一次区间 \(+1\) 拆成一段后缀 \(+1\) 和一段后缀 \(-1\)。注意到一次后缀 \(+1/-1\) 时至多只有一个位置发生向上/向下翻折,在这个位置前与目标的相对高度 \(-1/+1\),之后相对高度不变,那么此时面积的变化量容易用这个位置表示,我们现在的任务就是快速找到这个位置。
具体而言,设 \(h_i\) 表示直线在 \(x = i\) 处的相对高度,手玩容易发现当区间 \(+1\) 时,我们要找第一个 \(0/-1\),区间 \(-1\) 时,我们要找第一个 \(0/1\)。
现在我们要维护一个数据结构,支持区间 \(+1/-1\),区间找第一个 \(-1/0/1\),考虑分块,块内维护排序数组,修改时整块打标记,散块归并重构,询问时散块暴力,整块二分即可,平衡块长,时间复杂度 \(O(n \sqrt {n \log n})\),常数较小。
Code
#include <iostream>
#include <cmath>
#include <numeric>
#include <algorithm>
#include <vector>
using namespace std;
using LL = long long;
const int N = 1e5 + 5;
const int Mod = 1e9 + 7, Inv = (Mod + 1) / 2;
int n, m;
LL ans;
namespace Block {
  int len, cnt;
  int a[N], b[N], tag[N], bl[N], L[N], R[N];
  void build () {
    len = sqrt(n) * 0.4;
    for (int i = 0; i <= n; ++i) {
      bl[i] = i / len + 1;
    }
    cnt = bl[n];
    R[0] = -1;
    for (int i = 1; i <= cnt; ++i) {
      L[i] = R[i - 1] + 1;
      R[i] = min(n, L[i] + len - 1);
    }
    fill(a, a + n + 1, 0);
    iota(b, b + n + 1, 0);
    fill(tag, tag + cnt + 1, 0);
  }
  int first_val (int x, int y) {
    for (int i = x; i <= R[bl[x]]; ++i) {
      if (a[i] == y - tag[bl[x]]) {
        return i;
      }
    }
    for (int i = bl[x] + 1; i <= cnt; ++i) {
      if (a[b[R[i]]] < y - tag[i] || a[b[L[i]]] > y - tag[i]) continue;
      auto cmp = [&](int i, int j) -> bool {
        return a[i] < j;
      };
      auto it = lower_bound(b + L[i], b + R[i] + 1, y - tag[i], cmp);
      if (it != b + R[i] + 1 && a[*it] == y - tag[i]) return *it;
    }
    return n + 1;
  }
  int tmpa[N][2];
  int al[2];
  void add (int l, int r, int x) {
    r = min(r, n);
    auto rebuild = [&](int l, int r, int gl, int gr) -> void {
      al[0] = 0, al[1] = 0;
      for (int i = l; i <= r; ++i) {
        int o = b[i] >= gl && b[i] <= gr;
        tmpa[++al[o]][o] = b[i];
      }
      int p = l;
      auto cmp = [&](int i, int j) -> bool {
        return a[i] < a[j] || a[i] == a[j] && i < j;
      };
      for (int cur[2] = {1, 1}; cur[0] != al[0] + 1 || cur[1] != al[1] + 1; ) {
        if (cur[0] != al[0] + 1 && (cur[1] == al[1] + 1 || cmp(tmpa[cur[0]][0], tmpa[cur[1]][1]))) {
          b[p++] = tmpa[cur[0]][0], ++cur[0];
        }
        else {
          b[p++] = tmpa[cur[1]][1], ++cur[1];
        }
      }
    };
    if (bl[l] == bl[r]) {
      for (int i = l; i <= r; ++i) {
        a[i] += x;
      }
      rebuild(L[bl[l]], R[bl[l]], l, r);
    }
    else {
      for (int i = l; i <= R[bl[l]]; ++i) {
        a[i] += x;
      }
      for (int i = L[bl[r]]; i <= r; ++i) {
        a[i] += x;
      }
      rebuild(L[bl[l]], R[bl[l]], l, R[bl[l]]);
      rebuild(L[bl[r]], R[bl[r]], L[bl[r]], r);
      for (int i = bl[l] + 1; i <= bl[r] - 1; ++i) {
        tag[i] += x;
      }
    }
  }
}
void suf_add (int x) {
  int pos = min(Block::first_val(x, 0), Block::first_val(x, 1));
  ans += max(0, (n - pos) * 2 - 1);
  Block::add(x, pos, -1);
}
void suf_minus (int x) {
  int pos = min(Block::first_val(x, 0), Block::first_val(x, -1));
  ans -= max(0, (n - pos) * 2 - 1);
  Block::add(x, pos, 1);
}
int main () {
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  int T;
  cin >> T;
  while (T--) {
    cin >> n >> m;
    Block::build(), ans = 0;
    for (int i = 1, l, r; i <= m; ++i) {
      cin >> l >> r;
      suf_add(l), suf_minus(r);
      cout << ans % Mod * Inv % Mod << '\n';
    }
  }
  return 0;
}
T1012 图计算(HDU 7456)
考虑对于每一张图分别维护并查集,我们使用启发式合并,这样可以保证每个结点的 \(fa\) 就是它的最高级祖先,对于每一个结点,为它在所有图中的 \(fa\) 序列哈希即可。
Code
#include <iostream>
#include <vector>
#include <tuple>
#include <unordered_map>
using namespace std;
using LL = long long;
using Tp = tuple<int, int, int>;
const int N = 5e4 + 5, M = 105; 
int n, m, d, q;
struct Hash_Arr {
  int len; 
  struct Hash {
    int mod, base, len;
    int pw[M], now;
    void init (int mod_, int base_, int len_) {
      mod = mod_, base = base_, now = 0, len = len_;
      pw[0] = 1;
      for (int i = 1; i <= len; ++i) {
        pw[i] = 1ll * pw[i - 1] * base % mod;
      }
    }
    void add (int x, int y) { now = (now + 1ll * (mod + y) * pw[x]) % mod; }
  } ha[3];
  void init (int len_) {
    len = len_;
    ha[0].init(1000000007, 1000000009, len);
    ha[1].init(1000000021, 1000000033, len);
    ha[2].init(1000000087, 1000000093, len);
  }
  void add (int x, int y) {
    ha[0].add(x, y);
    ha[1].add(x, y);
    ha[2].add(x, y);
  }
  Tp get_val () { return make_tuple(ha[0].now, ha[1].now, ha[2].now); }
} h[N];
struct tHash {
  const int tB = 998244353, tP = tB * tB;
  int operator() (Tp x) const {
    return get<0>(x) + get<1>(x) * tB * get<2>(x) * tP;
  }
};
unordered_map<Tp, int, tHash> p;
LL ans; 
void add (Tp x) {
  int v = p[x]++;
  ans += v;
}  
void remove (Tp x) {
  int v = --p[x];
  ans -= v;
}
struct U {
  int fa[N], id;
  vector<int> vec[N];
  void init (int id_) {
    id = id_;
    fill(vec + 1, vec + n + 1, vector<int>());
    for (int i = 1; i <= n; ++i) {
      vec[i].push_back(i);
      fa[i] = i;
      h[i].add(id, i);
    }
  }
  void unite (int x, int y) {
    x = fa[x], y = fa[y];
    if (x == y) return;
    if (vec[x].size() < vec[y].size()) swap(x, y);
    for (auto v : vec[y]) {
      vec[x].push_back(v);
      remove(h[v].get_val());
      h[v].add(id, x - fa[v]);
      add(h[v].get_val());
      fa[v] = x;
    }
    vec[y].clear();
  }
} uf[M]; 
int main () {
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  int T;
  cin >> T;
  while (T--) {
    cin >> n >> m >> d >> q;
    for (int i = 1; i <= n; ++i) {
      h[i].init(d + 1);
    }
    for (int i = 1; i <= d + 1; ++i) {
      uf[i].init(i);
    }
    p.clear(), ans = 0;
    for (int i = 1; i <= n; ++i) {
      add(h[i].get_val());
    }
    for (int i = 1, u, v; i <= m; ++i) {
      cin >> u >> v;
      for (int j = 1; j <= d + 1; ++j) {
        uf[j].unite(u, v);
      }
    }
    for (int i = 1, u, v, w; i <= q; ++i) {
      cin >> u >> v >> w;
      uf[w].unite(u, v);
      cout << ans << '\n';
    }
  }
  return 0;
}
HDU-ACM 2024 Day2的更多相关文章
- hdu acm 1028  数字拆分Ignatius and the Princess III
		Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ... 
- HDU ACM 题目分类
		模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 104 ... 
- hdu acm 1166 敌兵布阵 (线段树)
		敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ... 
- hdu acm 2082  找单词
		找单词 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ... 
- HDU ACM 1325 / POJ 1308   Is It A Tree?
		Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ... 
- HDU ACM 1134 Game of Connections / 1130 How Many Trees?(卡特兰数)
		[题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=1134 [解题背景]这题不会做,自己推公式推了一段时间,将n=3和n=4的情况列出来了,只发现第n项与 ... 
- HDU ACM Eight
		题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 解题背景: 看到八数码问题,没有任何的想法,偶然在翻看以前做的题的时候发现解决过类似的一道题,不 ... 
- HDU ACM 1690 Bus System (SPFA)
		Bus System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ... 
- HDU ACM 1224 Free DIY Tour (SPFA)
		Free DIY Tour Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ... 
- HDU ACM 1869 六度分离(Floyd)
		六度分离 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ... 
随机推荐
- 【Vue】13 VueRouter Part3 路由守卫
			单页应用中,只存在一个HTML文件,网页的标签,是通过title标签显示的,我们在单页应用中如何修改? JS操作: window.document.title = "标签名称" 也 ... 
- agnostic在计算机领域的常用翻译 —— location-agnostic deployment option
			关于agnostic的翻译: 例子: NVIDIA OSMO scales workloads across distributed environments. For robotics worklo ... 
- 服务器上运行  xvbf 时报错  ——   Unknown encoder 'libx264'
			解决方法: 使用conda环境(不具体交代) conda install ffmpeg 成功运行: 
- 大连人工智能计算平台——华为昇腾AI平台——高性能计算HPC——如何在MPI中支持multiprocessing和fork操作——如何在HPC平台上使用pytorch——是否可以通过调度器的提交参数绕过HPC的计费系统
			本文要讨论的就是如何在MPI中支持multiprocessing和fork操作,但是这个问题同时也是如何在HPC平台如何使用pytorch的问题,可以说这两个问题其实是同一个问题,而这个问题的解决过程 ... 
- 代码随想录Day16
			513.找树左下角的值 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值. 假设二叉树中至少有一个节点. 示例 1: 输入: root = [2,1,3] 输出: 1 示 ... 
- redis集群之哨兵模式
			redis集群之哨兵模式 1.集群部署 安装配置可参考一下地址: https://www.cnblogs.com/zhoujinyi/p/5569462.html 2.与springboot集成 这里 ... 
- git push --recurse-submodules = on-demand 递归push
			I have the following project structure: root-project | |-- A | | | |-- C | |-- B A和B是根项目的子模块. C又是项目A ... 
- 国内IT行业67家外包公司,有多少程序员在里面待过?
			之前写过一篇关于外包公司的文章, <什么是软件外包公司?要不要去外包公司?> 很多粉丝看了后,感觉都在说自己, 存在即合理, 外包大幅度降(可)低(以)了(压)用(榨)人(更)成(多)本( ... 
- 基于docker搭建单机测试ELK
			说明:本次使用的windows系统,利用vm进行安装虚拟机,安装的只是单测试单机版elk. 一.下载vm 自行官网下载 二.安装centos7系统 自己有现成的镜像跳过,没有自行查找资料完成 三.进行 ... 
- python的命名风格(下划线篇)
			一个下划线开头的代表模块私有 用from xxx import * 时python会自动屏蔽带下划线的东西,想要取消屏蔽可以用__all__方法,但不建议(不符合规范) 两个下划线开头的代表类私有 
