loj516 「LibreOJ β Round #2」DP 一般看规律

Posted 逢山开路 遇水架桥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj516 「LibreOJ β Round #2」DP 一般看规律相关的知识,希望对你有一定的参考价值。

传送门:https://loj.ac/problem/516

【题解】

那段代码求的是相同的数中间隔最小的值。

离散后用set维护每个值出现次数,每次操作相当于合并两个set,这步可以启发式合并。

加元素的时候直接找前驱和后继即可。

学了新姿势:set中insert有返回的,可以访问.first来调用新插入元素的iterator

技术分享
# include <set>
# include <vector>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 1e5 + 10, M = 3e5 + 10;
const int mod = 1e9+7, inf = 2147483647;

int n, m, a[N];
struct quest {
    int x, y;
}q[N];
vector<int> ps;
set<int> s[M];
set<int>::iterator it, it2;
int ans[M], Ans = inf, id[M];

inline int getid(int x) {
    return lower_bound(ps.begin(), ps.end(), x) - ps.begin() + 1;
}

int main() {
    cin >> n >> m;
    for (int i=1; i<=n; ++i) {
        scanf("%d", a+i);
        ps.push_back(a[i]);
    }
    for (int i=1; i<=m; ++i) {
        scanf("%d%d", &q[i].x, &q[i].y);
        ps.push_back(q[i].x); ps.push_back(q[i].y);
    }
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    for (int i=1; i<=n; ++i) a[i] = getid(a[i]);
    for (int i=1; i<=m; ++i) q[i].x = getid(q[i].x), q[i].y = getid(q[i].y);
    for (int i=1; i<=n; ++i) s[a[i]].insert(i);
    for (int i=1; i<=ps.size(); ++i) {
        ans[i] = inf; id[i] = i;
        if(s[i].size() < 2) continue;
        for (it = s[i].begin(), it2 = ++s[i].begin(); it2 != s[i].end(); ++it, ++it2) 
            ans[i] = min(ans[i], *it2 - *it);
        Ans = min(Ans, ans[i]);
    }
    for (int i=1, X, Y, x, tans; i<=m; ++i) {
        X = q[i].x, Y = q[i].y;
        if(!s[id[X]].size()) {
            printf("%d\n", Ans);
            continue;
        }
        if(!s[id[Y]].size()) {
            swap(id[X], id[Y]);
            printf("%d\n", Ans);
            continue;
        }
        tans = min(ans[id[X]], ans[id[Y]]);
        if(s[id[X]].size() > s[id[Y]].size()) swap(id[X], id[Y]);
        for (it = s[id[X]].begin(); it != s[id[X]].end(); ++it) {
            x = *it;
            it2 = s[id[Y]].insert(x).first;
            ++it2;
            if(it2 != s[id[Y]].end()) tans = min(tans, *it2 - x);
            --it2;
            if(it2 != s[id[Y]].begin()) --it2, tans = min(tans, x - *it2);
        }
        s[id[X]].clear();
        ans[id[Y]] = tans;
        ans[id[X]] = inf;
        Ans = min(Ans, tans);
        printf("%d\n", Ans);
    }
    return 0;
}
View Code

 

以上是关于loj516 「LibreOJ β Round #2」DP 一般看规律的主要内容,如果未能解决你的问题,请参考以下文章

LOJ 「LibreOJ β Round #4」子集

loj526「LibreOJ β Round #4」子集

loj548 「LibreOJ β Round #7」某少女附中的体育课

「LibreOJ β Round #4」求和

「LibreOJ β Round #4」子集

「LibreOJ β Round #4」游戏