ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1707E Replace【倍增,ST表】

2022-07-22 20:05:25  阅读:176  来源: 互联网

标签:ch cup int Mod MN Replace CF1707E ST define


传送门

思路

学了析合树还不会做这题,感觉我真的没什么救/ll

对于这类跳若干步的问题,一个很自然的想法是预处理倍增数组,但这题的状态数量是 \(O(n^2)\) 的,看起来不能直接做。这时一个关键结论突然出现:设 \(f^k(l,r)\) 为 \([l,r]\) 操作 \(k\) 后的结果,那么若 \([l_1,r_1] \cup [l_2,r_2] = [l,r],[l_1,r_1] \cap [l_2,r_2] \neq \varnothing\),那么 \(f^k(l,r) = f^k(l_1,r_1) \cup f^k(l_2,r_2)\)。

证明考虑归纳,只需要证明如下命题:若 \([l_1,r_1] \cup [l_2,r_2] = [l,r],[l_1,r_1] \cap [l_2,r_2] \neq \varnothing\),那么 \(f(l,r) = f(l_1,r_1) \cup f(l_2,r_2),f(l_1,r_1) \cap f(l_2,r_2) \neq \varnothing\)。由两个区间相交能得到它们的值域相交,因此这个结论显然成立。

然后就很简单了,我们考虑设定若干关键区间,使得每个区间都能够被数量很少的交不为空的关键区间的并表示,ST 表恰好可以完成这个任务。询问时外面再倍增一下就行了。具体来说,设 \(L_{i,j,k}\) 表示区间 \([i,i+2^j-1]\) 操作 \(2^k\) 后的区间的左端点,\(R_{i,j,k}\) 类似,时间复杂度 \(O(n \log^2 n)\)。

具体实现的时候可能需要交换数组的某些维度来减少 cache miss。

Code
/*
最黯淡的一个 梦最为炽热
万千孤单焰火 让这虚构灵魂鲜活
至少在这一刻 热爱不问为何
存在为将心声响彻
*/
#include <bits/stdc++.h>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define int long long
#define mem(x, v, n) memset(x, v, sizeof(int) * (n))
#define mcpy(x, y, n) memcpy(x, y, sizeof(int) * (n))
#define lob lower_bound
#define upb upper_bound
using namespace std;

inline int read() {
	int x = 0, w = 1;char ch = getchar();
	while (ch > '9' || ch < '0') { if (ch == '-')w = -1;ch = getchar(); }
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x * w;
}

inline int min(int x, int y) { return x < y ? x : y; }
inline int max(int x, int y) { return x > y ? x : y; }

const int MN = 1e5 + 5;
const int Mod = 998244353;

inline int qPow(int a, int b = Mod - 2, int ret = 1) {
    while (b) {
        if (b & 1) ret = ret * a % Mod;
        a = a * a % Mod, b >>= 1;
    }
    return ret;
}

// #define dbg

int N, M, a[MN], L[18][18][MN], R[18][18][MN], lg[MN], bin[MN];

inline int QryL(int i, int l, int r) {
    int t = lg[r - l + 1];
    return min(L[i][t][l], L[i][t][r - bin[t] + 1]);
}
inline int QryR(int i, int l, int r) {
    int t = lg[r - l + 1];
    return max(R[i][t][l], R[i][t][r - bin[t] + 1]);
}

signed main(void) {
    N = read(), M = read();
    for (int i = 1; i <= N; i++) L[0][0][i] = R[0][0][i] = read();
    lg[0] = -1;
    for (int i = 1; i <= N; i++) lg[i] = lg[i >> 1] + 1;
    bin[0] = 1;
    for (int i = 1; i <= 17; i++) bin[i] = bin[i - 1] << 1;
    for (int j = 1; j <= 17; j++) 
        for (int i = 1; i + bin[j] - 1 <= N; i++) {
            L[0][j][i] = min(L[0][j - 1][i], L[0][j - 1][i + bin[j - 1]]);
            R[0][j][i] = max(R[0][j - 1][i], R[0][j - 1][i + bin[j - 1]]);
        }
    for (int k = 1; k <= 17; k++) 
        for (int j = 0; j <= 17; j++) 
            for (int i = 1; i + bin[j] - 1 <= N; i++) {
                L[k][j][i] = QryL(k - 1, L[k - 1][j][i], R[k - 1][j][i]);
                R[k][j][i] = QryR(k - 1, L[k - 1][j][i], R[k - 1][j][i]);
            }
    while (M--) {
        int l = read(), r = read();
        int res = 1;
        if (l == 1 && r == N) {
            puts("0");
            continue;
        }
        int nl = 0, nr = 0;
        for (int k = 17; ~k; k--) {
            nl = QryL(k, l, r), nr = QryR(k, l, r);
            if (nl > 1 || nr < N) l = nl, r = nr, res += 1 << k;
        }
        nl = QryL(0, l, r), nr = QryR(0, l, r);
        if (nl > 1 || nr < N) res = -1;
        printf("%lld\n", res);
    }
    return 0;
}

标签:ch,cup,int,Mod,MN,Replace,CF1707E,ST,define
来源: https://www.cnblogs.com/came11ia/p/16507858.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有