首页 > 其他分享 >G2. Yunli's Subarray Queries (hard version)

G2. Yunli's Subarray Queries (hard version)

时间:2024-09-05 22:52:42浏览次数:8  
标签:G2 int hard tp st leq version query ldots

G2. Yunli's Subarray Queries (hard version)

This is the hard version of the problem. In this version, it is guaranteed that $r \geq l+k-1$ for all queries.

For an arbitrary array $b$, Yunli can perform the following operation any number of times:

  • Select an index $i$. Set $b_i = x$ where $x$ is any integer she desires ($x$ is not limited to the interval $[1,n]$).

Denote $f(b)$ as the minimum number of operations she needs to perform until there exists a consecutive subarray$^{\text{∗}}$ of length at least $k$ in $b$.

Yunli is given an array $a$ of size $n$ and asks you $q$ queries. In each query, you must output $\sum_{j=l+k-1}^{r} f([a_l, a_{l+1}, \ldots, a_j])$.

$^{\text{∗}}$If there exists a consecutive subarray of length $k$ that starts at index $i$ ($1 \leq i \leq |b|-k+1$), then $b_j = b_{j-1} + 1$ for all $i < j \leq i+k-1$.

Input

The first line contains $t$ ($1 \leq t \leq 10^4$) — the number of test cases.

The first line of each test case contains three integers $n$, $k$, and $q$ ($1 \leq k \leq n \leq 2 \cdot 10^5$, $1 \leq q \leq 2 \cdot 10^5$) — the length of the array, the length of the consecutive subarray, and the number of queries.

The following line contains $n$ integers $a_1, a_2, ..., a_n$ ($1 \leq a_i \leq n$).

The following $q$ lines contain two integers $l$ and $r$ ($1 \leq l \leq r \leq n$, $r \geq l+k-1$) — the bounds of the query.

It is guaranteed the sum of $n$ over all test cases does not exceed $2 \cdot 10^5$ and the sum of $q$ over all test cases does not exceed $2 \cdot 10^5$.

Output

Output $\sum_{j=l+k-1}^{r} f([a_l, a_{l+1}, \ldots, a_j])$ for each query on a new line.

Example

Input

3
7 5 3
1 2 3 2 1 2 3
1 7
2 7
3 7
8 4 2
4 3 1 1 2 4 3 2
3 6
1 5
5 4 2
4 5 1 2 3
1 4
1 5

Output

6
5
2
2
5
2
3

Note

In the second query of the first testcase, we calculate the following function values:

  • $f([2,3,2,1,2])=3$ because Yunli can set $b_3=4$, $b_4=5$, and $b_5=6$, making a consecutive subarray of size $5$ in $3$ moves.
  • $f([2,3,2,1,2,3]=2$ because we can set $b_3=0$ and $b_2=-1$, making a consecutive subarray of size $5$ in $2$ moves (starting at position $2$)

The answer to this query is $3+2=5$.

 

解题思路

  逆天 Div.4,想着补个 G 题的结果一题都不会(),G3 的难度预测甚至到了 2800 分,直接弃疗.jpg。

  做 G1 的时候一直从差分的角度去想,结果做不出来,题解给出的性质反正我是观察不出来的。假设子数组 $a_l, a_{l + 1}, \ldots, a_r$ $(r-l+1=k)$ 满足连续性,那么对于任意 $l \leq i \leq j \leq r$,有 $a_j - a_i = j - i$,移项得到 $a_i - i = a_j - j$。定义 $b_i = a_i - i$,因此如果子数组要满足连续性,等价于 $b_l = b_{l + 1} = \ldots = b_r$。假设出现次数最多 $b_i$ 的值为 $x$,我们将 $b_i$ 都变成 $x$,就可以用最少的修改将子数组变得连续。

  定义 $f(i) \, (1 \leq i \leq n-k+1)$ 表示将子数组 $a_i, a_{i+1}, \ldots, a_{i+k-1}$ 变得连续的最少修改次数。可以用大小为 $k$ 的滑动窗口预处理出每个 $f(i)$,开个 std::map 维护窗口内 $a_i - i$ 的个数,std::multiset 维窗口内值出现的次数。对于 G1 就可以 $O(1)$ 查询了。

  G2 的思路也显而易见了,就是在 $f(l), f(l+1), \ldots, f(r-k+1)$ 中,求每个前缀的最小值的和,即 $\sum\limits_{i = l}^{r-k+1}{\min\limits_{l \leq j \leq i}{f(j)}}$。不过题解给出来的做法我也想不出来就是了。

  做法是按询问的左端点从大到小离线处理,下面解释这样做的原因。不妨假设我们当前维护出了 $g(i), g(i+1), \ldots, g(n-k+1)$,其中 $g(j) \, (i \leq j \leq n-k+1)$ 表示前缀最小值即 $\min\limits_{i \leq x \leq j}{f(x)}$。对于询问只需求出关于 $g(j)$ 某个前缀的和(此时的 $i$ 一定是该询问的左端点)。由于询问的左端点依次减小,因此需要从后往前依次把 $f(i)$ 考虑进来去维护每个 $g(j)$。

  现在把 $f(i-1)$ 考虑进来,并相应地将 $g(j)$ 都更新成 $\min\limits_{i-1 \leq x \leq j}{f(x)}$,如何维护呢?只需从 $i-1$ 开始往右找到第一个比 $f(i-1)$ 小的 $f(u)$(可以维护一个单调栈),并将 $g(i-1), g(i), \ldots, g(u-1)$ 都更新成 $f(i-1)$ 即可。由于涉及到区间修改,查询区间和,因此可以用线段树去维护 $g(j)$。

  AC 代码如下,时间复杂度为 $O(q \log{q} + (q + n) \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5;

int a[N], f[N];
int l[N], r[N], p[N];
struct Node {
    int l, r, tag;
    LL s;
}tr[N * 4];
int stk[N];
LL ans[N];

void build(int u, int l, int r) {
    tr[u] = {l, r, -1};
    if (l != r) {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
    }
}

void upd(int u, int c) {
    tr[u].s = (tr[u].r - tr[u].l + 1ll) * c;
    tr[u].tag = c;
}

void pushdown(int u) {
    if (tr[u].tag == -1) return;
    upd(u << 1, tr[u].tag);
    upd(u << 1 | 1, tr[u].tag);
    tr[u].tag = -1;
}

void modify(int u, int l, int r, int c) {
    if (tr[u].l >= l && tr[u].r <= r) {
        upd(u, c);
    }
    else {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, c);
        if (r >= mid + 1) modify(u << 1 | 1, l, r, c);
        tr[u].s = tr[u << 1].s + tr[u << 1 | 1].s;
    }
}

LL query(int u, int l, int r) {
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].s;
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (r <= mid) return query(u << 1, l, r);
    if (l >= mid + 1) return query(u << 1 | 1, l, r);
    return query(u << 1, l, r) + query(u << 1 | 1, l, r);
}

void solve() {
    int n, m, k;
    cin >> n >> k >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        a[i] -= i;
    }
    map<int, int> mp;
    multiset<int> st;
    for (int i = 0; i < n; i++) {
        st.insert(0);
    }
    for (int i = 1; i <= n; i++) {
        st.erase(st.find(mp[a[i]]));
        st.insert(++mp[a[i]]);
        if (i - k > 0) {
            st.erase(st.find(mp[a[i - k]]));
            st.insert(--mp[a[i - k]]);
        }
        if (i >= k) f[i - k + 1] = k - *st.rbegin();
    }
    for (int i = 1; i <= m; i++) {
        cin >> l[i] >> r[i];
        p[i] = i;
    }
    sort(p + 1, p + m + 1, [&](int i, int j) {
        return l[i] > l[j];
    });
    build(1, 1, n - k + 1);
    int tp = 0;
    stk[++tp] = n - k + 2;
    f[n - k + 2] = -1;
    for (int i = 1, j = n - k + 1; i <= m; i++) {
        while (j >= l[p[i]]) {
            while (f[stk[tp]] > f[j]) {
                tp--;
            }
            modify(1, j, stk[tp] - 1, f[j]);
            stk[++tp] = j--;
        }
        ans[p[i]] = query(1, l[p[i]], r[p[i]] - k + 1);
    }
    for (int i = 1; i <= m; i++) {
        cout << ans[i] << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round 971 (Div. 4) Editorial:https://codeforces.com/blog/entry/133296

标签:G2,int,hard,tp,st,leq,version,query,ldots
From: https://www.cnblogs.com/onlyblues/p/18399273

相关文章

  • pg库psycopg2
    importpsycopg2classPostgreSQLDB:def__init__(self,host,port,user,password,database):self.host=hostself.port=portself.user=userself.password=passwordself.database=databaseself.co......
  • pymongo.errors.ConfigurationError: Server at localhost:27017 reports wire versio
    当你的PyMongo版本比较新时,如当前使用版本为v4.8.0,如果你尝试连接到MongoDBServerv3.4或更早版本,PyMongo可能会引发以下错误:pymongo.errors.ConfigurationError:Serveratlocalhost:27017reportswireversion5,butthisversionofPyMongorequiresatleast6(Mo......
  • vscode 找不到 NETFramework,Version=v4.7.1 报错,简单解决办法
    当我们用vscode开发时,会发现有这样的报错:Thereferenceassembliesforframework“.NETFramework,Version=v4.7.1”werenotfound.Toresolvethis,installtheSDKorTargetingPackforthisframeworkversionorretargetyourapplicationtoaversionofthef......
  • CF 2010 C2. Message Transmission Error (hard version) (*1700) 字符串+哈希
    CF2010C2.MessageTransmissionError(hardversion)(*1700)字符串+哈希题目链接题意:给你一个字符串,让你判断是否是由某个字符串首尾拼接重叠而成的。思路:做法很多,最暴力就直接枚举字符串长度,然后哈希即可。代码:#include<bits/stdc++.h>usingnamespacestd;#def......
  • CF1998E2 Eliminating Balls With Merging (Hard Version)
    原题链接考虑对于每个\(i\),算出向左扩展到\(1\)时向右至少和至多扩展到哪里,记为\(minr\)和\(maxr\)。那么也就是说每个\(i\)会对\(minr\simmaxr\)做出贡献,差分一下就可以了。重点是怎么计算这两个东西。先说\(maxr\)。如果暴力跳,过程是:先向左扩展直到不能扩展,然后......
  • CF 2002 D1. DFS Checker (Easy Version) (*1900)思维
    CF2002D1.DFSChecker(EasyVersion)(*1900)思维题目链接题意:给你一棵\(n\)个节点组成的完全二叉树,并给出一个排列\(p\)。接下来进行\(q\)次询问。每次询问给你\(x\)和\(y\),你需要交换\(p_x\)和\(p_y\)。并且回答交换之后的排列\(p\)是否是这棵完全二叉树......
  • ShardingSphere-JDBC实现数据加解密
    一、什么是ShardingSphere?        ShardingSphere定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。ApacheShardingSphere旨......
  • Apache顶级项目ShardingSphere — SQL Parser的设计与实现
    导语:SQL作为现代计算机行业的数据处理事实标准,是目前最重要的数据处理接口之一,从传统的DBMS(如MySQL、Oracle),到主流的计算框架(如spark,flink)都提供了SQL的解析引擎,因此想对sql进行精细化的操作,一定离不开SQLParser。ApacheShardingSphere是一套开源的分布式数据库中间件解决方......
  • 对比 Vitess,ShardingSphere 有哪些不同
    本篇为InfoQ中文站供稿原文链接:https://www.infoq.cn/article/NHSAAmN*MfpLiTiTTEu5?from=timeline&isappinstalled=0ShardingSphere是什么?ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规......
  • Apache顶级项目ShardingSphere — SQL Parser的设计与实现
    导语:SQL作为现代计算机行业的数据处理事实标准,是目前最重要的数据处理接口之一,从传统的DBMS(如MySQL、Oracle),到主流的计算框架(如spark,flink)都提供了SQL的解析引擎,因此想对sql进行精细化的操作,一定离不开SQLParser。ApacheShardingSphere是一套开源的分布式数据库中间件解决方案......