AcWing 4412. 构造数组

AcWing 4412. 构造数组(三种解法)

思路分析

经分析可得,

\[若a_i = a_j,则 b_i <= b_{i + 1} <= ... <= b_j\\ 又\because b_i=b_j\,\,\,\therefore b_i = b_{i + 1} = ... = b_j \]

所以只需要去统计有多少个这样的区间,然后乘2即可(因为每一个区间都有两种选择)

法一:区间合并

基础

防止umap被卡的小技巧:1. 初始化一个大的长度(见代码);2. here;3.换成map

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int mod = 998244353, N = 2e5 + 5;
int n, m, cnt;
pair <int, int> p[N];

void test() {
    for (int i = 0; i < m; i ++)
        cout << p[i].first << ' ' << p[i].second << endl;
}

signed main () {
    unordered_map <int, int> L(300000), R(300000);
    
    cin >> n ;
    for (int i = 1; i <= n; i ++) {
        int t;cin >> t;
        R[t] = i;
        if (!L.count(t))
            L[t] = i; //左端点只用更新一次
    }
    
    int m = 0;
    for (auto& [i, v]:L) //高级做法 C++17才能用
        p[m ++] = {L[i], R[i]};

    sort (p, p + m);
    
    //test();

    int l = -1, r = -1;
    cnt = m;
    for (int i = 0; i < m; i ++) {
        if (p[i].first <= r)
            r = max (r, p[i].second), cnt --;

        else 
            l = p[i].first, r = p[i].second;
    }

    int ans = 0;
    cnt --;
    for (int i = 0; i < cnt; i ++)
        ans = ans * 2 % mod;
    cout << ans << endl;

}
//bi 到 bj之间的所有数字都要相等
//按照段来划分

法二:离散化 + 差分

染色思想:点坐标 * 2,统计被覆盖的次数,出现0就代表该区间结束,准备进入下一个区间

法三:并查集

这是一种通用思路(并查集常见操作)

把整体视为一个长线段。
每一个区间内的点都向右端点合并,最后就可以统计区间个数了

posted @ 2022-04-24 13:22  Sakana~  阅读(28)  评论(0编辑  收藏  举报