跳转至

GMOJ

8113. 【2022.10.7联考noip模拟】Talulah

题意

给定长度为 \(n\) 的排列 \(p\),定义集合 \(S_i = \{j \mid j \ge i \land \max_{k \in [i,j]} p_k = p_j\}\)

给定 \(q\) 次询问 \(l,r\),求 \(\sum_{x,y \in [l,r]} |S_x \cap S_y|\)

\(n,q \le 2.5 \times 10^5\)

思考

考虑钦定 \(x<y\),如下图所示:

图解

发现 \(\forall i \ge y\)\(i \in S_x \Rightarrow i \in S_y\)

Proof: 因为 \(i \in S_x\),所以 \(\max_{k \in [x,i]} p_k = p_i\),因此显然 \(\max_{k \in [y,i]} p_k = p_i\),即 \(i \in S_y\)\(\square\)

因此 \(|S_x \cap S_y| = |S_x \cap [x,y)| + |S_y|\)

考虑把这两个部分分开处理,发现所有 \(|S_y|\) 即为 \(\sum_{i \in [l,r]} (i-l)|S_i|\),可以用前缀和 \(\mathrm O(1)\) 计算。

考虑计算 \(\sum_{l \le x \lt y \le r} |S_x \cap [x,y)|\),如下图所示:

图解

正难则反,考虑抛弃 \(y\) 的限制,而是计算 \(i \in S_x\) 的贡献。

发现 \(\forall i \in S_x \cap [x,r]\),对于 \(\forall y \gt i\) 都有 \(1\) 的贡献,即原式等于 \(\sum_{i \in S_x \cap [x,r]} r-i\)

发现这个不好维护,于是正难则反,考虑计算 \(\forall i \in [l,r]\)\(x \le i\) 的贡献。

\(\mathrm{pre}_i = \max_{j \lt i} {j \mid p_j \gt p_i}\),即 \(i\) 前第一个大于 \(i\) 的元素的位置,并记 \(p_0 = \infty\)

发现 \(\forall i \in [l,r]\)\(i\)\(x \in (\mathrm{pre}_i,i]\)\(r-i\) 的贡献。

由于我们不清楚 \(r\) 的值,因此我们维护 \(r\) 的系数即可。

图解

如上图,考虑用线段树维护区间加与区间和。

考虑 \(i \in [l,r]\) 这条限制,容易发现当 \(i \lt l\) 时,\(i\)\([l,r]\) 无贡献;当 \(i \gt r\) 时,如上图的 \(j\),会对 \([l,r]\) 产生多余的贡献。

因此我们把询问离线并按右端点排序,依次加点即可。

最后别忘了我们计算的是 \(x \lt y\) 的答案,剩下部分是 naive 的。

如果强制在线的话,可以用可持久化线段树 + 标记永久化解决,时间复杂度同为 \(\mathrm O((n+q) \log n)\)

8081.【2024年SD省队集训 day2】反转了 (flip)

题意

给定长度为 \(N\) 的数组 \(A\),定义 \(S_0 = 0\)\(S_i = \sum_{j=1}^i A_j(i \in [1,N])\)

\(K \in [0,N]\),求解:

  • 至多反转 \(K\) 个元素的符号,求 \(\max_{i \in [0,N]} {S_i}\) 的最大值。

朴素解法

暴力枚举 \(K\),并枚举 \(i \in [0,N]\),假定 \(S_i = \max_{j \in [0,N]} {S_j}\),显然最优方案为反转前 \(i\) 个元素中绝对值最大的 \(K\) 个元素。

\(B_i = \max(0,-A_i)\),那么第 \(i\) 段前缀对 \(K\) 的贡献为 \(C(i,K) = S_i + 2 W(i,K)\),其中 \(W(i,K)\)\(\{B_1,B_2,\dots,B_i\}\) 中的前 \(K\) 大元素的和。

答案即为 \(\max{C(i,K)}\)

注意当 \(i \lt K\) 时,\(W(i,K) = \sum_{j=1}^i B_j\)

\(W(i,K)\) 可以用主席树在 \(O(\log N)\) 时间内求得。

总时间复杂度 \(O(N ^ 2 \log N)\),期望得分 30。

优化

\(f_K\) 表示 \(\min \{i | \forall j,C(i,K) \ge C(j,K)\}\),即使得 \(C(i,K)\) 最大的最小的 \(i\) 值。

容易发现 \(f\) 非严格单调递增。

于是便如 ABC348G 一样,用分治 + 主席树解决。

单调性证明

实践是检验真理的唯一标准
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int n,a[N + 2];
long long s[N + 2];
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
    for(int i=1; i<=n; ++i) s[i]=s[i-1]+a[i];
    int lst=-1;
    for(int i=0; i<=n; ++i) {
        multiset<int> st;
        ll sum=0,ans=0,k=0;
        for(int j=1; j<=n; ++j) {
            if(i!=0&&a[j]<0&&(st.size()<i||*st.begin()<-a[j])) {
                if(st.size()==i) {
                    sum-=*st.begin();
                    st.erase(st.begin());
                }
                sum+=-a[j];
                st.insert(-a[j]);
            }
            if(s[j]+sum*2>ans) ans=s[j]+sum*2,k=j;
        }
        assert(lst<=k);
        lst=k;
        printf("%lld ",ans);
    }
    return 0;
}

考虑使用反证法,假设 \(\exists i,f_i > f_{i+1}\),设 \(f_i = x,f_{i+1} = y\)

因为 \(f_i = x\),于是有

\[ \begin{aligned} & C(y,i) \lt C(x,i) \\ & S_y + 2W(y,i) \lt S_x + 2W(x,i) \\ & S_y - S_x + 2W(y,i) - 2W(x,i) \lt 0 \\ \end{aligned} \]

因为 \(f_{i+1} = y\),于是有

\[ \begin{aligned} C(y,i+1) & \ge C(x,i+1) \\ S_y + 2W(y,i+1) & \ge S_x + 2W(x,i+1) \\ S_y - S_x + 2W(y,i+1) - 2W(x,i+1) & \ge 0 \\ & \gt S_y - S_x + 2W(y,i) - 2W(x,i)\\ W(y,i+1) - W(x,i+1) & \gt W(y,i) - W(x,i) \\ W(y,i+1) - W(y,i) & \gt W(x,i+1) - W(x,i) \\ \end{aligned} \]

这显然是矛盾的,因为 \(y<x\)\(W(y,i+1) - W(y,i)\) 相当于 \(\{B_1,B_2,\dots,B_x\}\) 中的第 \(i+1\) 大的元素,但是 \(\{B_1,B_2,\dots,B_y\} \subset \{B_1,B_2,\dots,B_x\}\),于是必有 \(W(y,i+1) - W(y,i) \le W(x,i+1) - W(x,i)\),矛盾。

因此,\(f\) 是非严格单调递增的。

其他例题