首页 > 其他分享 >UNR#4 Day2

UNR#4 Day2

时间:2024-06-04 10:13:34浏览次数:6  
标签:UNR int ll Day2 mid mathcal 复杂度 qn

A. 同构判定鸭

既然要输出字典序最小的坏串,直觉是它肯定不长(证明不会,看 官解),考虑确定坏串的长度。

设 \(S_{u, k}\) 表示从 \(u\) 出发长度为 \(k\) 的路径的配对串的集合,我们要做的就是找到最小的 \(k\),使得 \(\bigcup {S_1}_{u, k} \ne \bigcup {S_2}_{u, k}\)。

Hash 即可。

确定长度之后贪心确定坏串,需要记录长度为 \(k\) 的路径中以某个字母开头的哈希值,可以 DP 实现。

时间复杂度 \(\mathcal O(nm)\)。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 510, M = 3010, MOD = 1e9 + 7;

mt19937 eng(random_device{}());

int w[N << 1][128];

struct Graph {
    int n, m;
    int hs[N << 1], val[N], con[N], f[N << 1][N];

    struct Edge {int u, v; char c;} e[M];

    inline void init() {fill(val + 1, val + n + 1, 1);}
    inline void lock() {memcpy(val, con, sizeof(val));}

    void input() {
        cin >> n >> m;
        for (int i = 1; i <= m; i++) cin >> e[i].u >> e[i].v >> e[i].c;
        init();
    }
    
    int calc(int x) {
        memset(con, 0, sizeof(con));
        for (int i = 1; i <= m; i++) con[e[i].v] = (con[e[i].v] + 1ll * val[e[i].u] * w[x][e[i].c]) % MOD;
        int res = 0;
        for (int i = 1; i <= n; i++) res = (res + con[i]) % MOD;
        return lock(), res;
    }

    void dp(int T) {
        for (int i = 1; i <= n; i++) f[T + 1][i] = 1;
        for (int i = T; i; i--) for (int j = 1; j <= m; j++) {
            f[i][e[j].u] = (f[i][e[j].u] + 1ll * w[i][e[j].c] * f[i + 1][e[j].v]) % MOD;
        }
    }

    int spec(int x, char c) {
        memset(con, 0, sizeof(con));
        for (int i = 1; i <= m; i++) if (e[i].c == c) con[e[i].v] = (con[e[i].v] + 1ll * val[e[i].u] * w[x][e[i].c]) % MOD;
        int res = 0;
        for (int i = 1; i <= n; i++) res = (res + 1ll * con[i] * f[x + 1][i]) % MOD;
        return res;
    }
} G1, G2;

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    G1.input(), G2.input();
    int n = 1e5;
    for (int i = 1; i <= n; i++) for (int j = 'a'; j <= 'z'; j++) w[i][j] = eng() % MOD;
    int len = 0;
    for (int i = 1; i <= n; i++) if (G1.calc(i) != G2.calc(i)) {len = i; break;}
    if (!len) {cout << "Same"; return 0;}
    G1.dp(len), G2.dp(len);
    G1.init(), G2.init();
    for (int i = 1; i <= len; i++) for (char c = 'a'; c <= 'z'; c++) {
        if (G1.spec(i, c) != G2.spec(i, c)) {
            cout << c;
            G1.lock(), G2.lock();
            break;
        }
    }
    return 0;
}

B. 己酸集合

对每个 \(j\) 求满足 \(x_i^2 + (y_i - z_j)^2 \le R_j^2\) 的 \(i\) 的个数。

展开,写成 \(x_i^2 + y_i^2 \le 2z_jy_i + R_j^2 - z_j^2\)。

记 \(X_i = y_i, Y_i = x_i^2 + y_i^2, k_j = 2z_j, b_j = R_j^2 - z_j^2\),则原式又可以写作:\(k_jX_i + b_j \ge Y_i\),即 \((X_i, Y_i)\) 在直线 \(l_j: y = k_jx + b_j\) 的下方。

对每个询问暴力判断,时间复杂度 \(\mathcal O(qn)\)。

把询问按 \(k_j\) 离线,维护点的相对顺序,然后二分。

具体地,在一个确定的 \((k, b)\) 下,\((X_i, Y_i)\) 优于 \((X_j, Y_j)\) 当且仅当 \(Y_i - kX_i < Y_j - kX_j\),又因为最开始 \(k \to -\infin\),所以按 \(X\) 升序(\(X\) 相同时按 \(Y\) 升序)排序是对的,然后需要每个满足 \(i < j\) 的点对 \((i, j)\) 求出什么时候交换位置即可。

  • 如果 \(X_i = X_j\),那不可能有位置的交换。

  • 否则则由最初的排序有 \(X_j > X_i\),要满足的新式子是 \(Y_j - kX_j < Y_i - kX_i\),即 \(k(X_i - X_j) < Y_i - Y_j\),同除 \(X_i - X_j\) 不等号方向要改变,即 \(k > \dfrac{Y_i - Y_j}{X_i - X_j}\),然后我们就知道何时 \((i, j)\) 应交换位置了。

最后对每个询问在维护相对顺序的同时二分查找就能数出个数了,时间复杂度 \(\mathcal O((n^2 + q)\log n)\)。

分块平衡一下预处理和查询的时间复杂度,设块长为 \(B\),则时间复杂度为 \(\mathcal O\left(\left(nB + \dfrac{qn}B\right)\log n\right)\)。

取 \(B = \sqrt q\) 最优,时间复杂度 \(\mathcal O\left(n\sqrt q\log n\right)\)。

代码

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

constexpr int N = 12010, Q = 1e6 + 10;

int n, qn, ans[Q], pos[N];

struct Point {
    ll x, y;

    Point() {}
    Point(ll x, ll y) : x(y), y(x * x + y * y) {}

    bool operator<(const Point &rhs) const {return x != rhs.x ? x < rhs.x : y < rhs.y;}
} p[N];

struct Query {
    int k; ll b; int id;

    Query() {}
    Query(ll z, ll r, int id) : k(z << 1), b(r * r - z * z), id(id) {}

    bool operator<(const Query &rhs) const {return k != rhs.k ? k < rhs.k : b < rhs.b;}
} q[Q];

struct Change {
    int x, y; double k;
    
    bool operator<(const Change &rhs) const {return k < rhs.k;}

    void work() {if (pos[x] < pos[y]) swap(p[pos[x]], p[pos[y]]), swap(pos[x], pos[y]);}
} c[Q];

int main() {
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> qn;
    for (int i = 1, x, y; i <= n; i++) cin >> x >> y, p[i] = Point(x, y);
    for (int i = 1, z, r; i <= qn; i++) cin >> z >> r, q[i] = Query(z, r, i);
    sort(q + 1, q + qn + 1);

    auto getans = [&](int i, int L, int R) -> void {
        int l = L, r = R, mid, res = L - 1;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (q[i].k * p[mid].x + q[i].b >= p[mid].y) res = mid, l = mid + 1;
            else r = mid - 1;
        }
        ans[q[i].id] += res - L + 1;
    };

    auto solve = [&](int l, int r) -> void {
        int m = 0;
        for (int i = l; i <= r; i++) for (int j = i + 1; j <= r; j++) if (p[i].x != p[j].x) {
            double k = 1.0 * (p[i].y - p[j].y) / (p[i].x - p[j].x);
            if (k <= q[qn].k) c[++m] = Change{i, j, k};
        }
        stable_sort(c + 1, c + m + 1);
        for (int i = 1, j = 1; i <= qn; i++) {
            while (j <= m && c[j].k < q[i].k) c[j++].work();
            getans(i, l, r);
        }
    };

    sort(p + 1, p + n + 1), iota(pos + 1, pos + n + 1, 1);
    int len = sqrt(qn) / 1.5, m = (n + len - 1) / len;
    for (int i = 1; i <= m; i++) solve((i - 1) * len + 1, min(i * len, n));
    for (int i = 1; i <= qn; i++) cout << ans[i] << '\n';
    return 0;
}

C. 挑战哈密顿

咕咕咕咕咕咕………………

标签:UNR,int,ll,Day2,mid,mathcal,复杂度,qn
From: https://www.cnblogs.com/chy12321/p/18230246

相关文章

  • [ROS报错问题]SystemError: initialization of cv_bridge_boost raised unreported ex
            在运行ROS代码时,很多人会使用到cv_bridge库,这个库的主要功能是帮助在ROS的图像消息(sensor_msgs/Image)和OpenCV的图像格式(cv::Mat)之间进行转换。然而,有时在使用cv_bridge时会遇到一个让人头疼的问题,即报错:fromcv_bridge.boost.cv_bridge_boostimportcvt......
  • Day21.函数的类型提示
    1.函数的类型提示_函数常规传参2.函数的类型提示_函数参数设置默认值3.函数的类型提示__annotations__方法查看参数传参类型 ......
  • 【WEEK14】 【DAY2】Shiro第七部分【中文版】
    2024.5.28Tuesday接上文【WEEK14】【DAY1】Shiro第六部分【中文版】目录15.8.Shiro整合Thymeleaf15.8.1.修改pom.xml添加依赖15.8.1.1.shiro-thymeleaf整合包导入15.8.1.2.当前完整的pom文件15.8.2.修改ShiroConfig.java15.8.3.修改index.html15.8.4.给root用户开放......
  • 动手学机器学习入门之Day2-梯度下降和多元线性回归
    前言前面我们已经学习的最小二乘法属于多元线性回归的主要概念,所以在看这篇文章之前,请确保你已经了解了最小二乘法,详情请见我的博客动手学机器学习入门之Day1。在机器学习领域,梯度下降和多元线性回归是两个至关重要的概念,它们为我们理解和构建复杂模型提供了基础。梯度下降......
  • Unreal 浅谈TWeakObjectPtr
    【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!前言在Unreal的开发过程中,正确的引用和管理UObject是十分重要的,尤其Unreal有着它自己的UObject的GC机制,这使得对UObject的有效引用和管理变得尤为......
  • UNR#3 Day2
    A.白鸽是否有解即判欧拉回路,判每个结点的度数是否都是偶数和有边的的结点是否与\(1\)号结点连通即可。因为最后形成的是一个封闭图形,大可把\(x\)轴正方向看做一条射线,我们每由上至下穿过这条射线会对答案产生\(1\)的贡献,反之,从下至上穿过这条射线就会对答案产生\(-1\)......
  • 【WEEK14】 【DAY2】Shiro Part 7【English Version】
    2024.5.28TuesdayContinuationfromprevious【WEEK14】【DAY1】ShiroPart6【EnglishVersion】Contents15.8.IntegrateShirowithThymeleaf15.8.1.Modifypom.xmltoAddDependencies15.8.1.1.Importingtheshiro-thymeleafIntegrationPackage15.8.1.2.......
  • [CEOI2010 day2] pin
    [CEOI2010day2]pin题目信息题目链接LuoguP6521题目描述给定\(n\)个长度为\(4\)的字符串,你需要找出有多少对字符串满足恰好\(D\)个对应位置的字符不同。输入格式输入第一行两个整数\(n,D\)。接下来的\(n\)行,每行一个长度为\(4\)的字符串。输出格式输出一行......
  • UNR#3 Day1
    A.鸽子固定器把固定器按\(s\)排序。如果选的个数\(<m\),选出来的一定是一个连续段,否则再多选夹在中间的固定器一定优。如果选的个数\(=m\),按牢固度从小到大考虑每一个固定器,找以当前固定器为最小牢固度的长度为\(m\)的最优序列,分讨几种情况之后不难发现忽略牢固度更小......
  • 代码随想录算法训练Day20|LeetCode654-最大二叉树、LeetCode617-合并二叉树、LeetCode
    最大二叉树题目描述力扣654-最大二叉树给定一个不重复的整数数组nums。最大二叉树可以用下面的算法从nums递归地构建:创建一个根节点,其值为nums中的最大值。递归地在最大值左边的子数组前缀上构建左子树。递归地在最大值右边的子数组后缀上构建右子树。......