题解:CF2077E Another Folding Strip
KingPowers · · 题解
挺有意思的一道题,部分内容参考官方题解,本题解将对所有的结论给出严谨证明。
首先转化掉折叠操作,显然对于两个奇偶性相同的下标,无论怎么折叠都无法使它们重合。进一步地,不难发现一次操作其实等价于选出一个相邻下标奇偶性不同的子序列都
先考虑怎么计算整个
注意到一个性质是,对于任意一个子段
令一次操作选择的子序列的下标集合为
-
初始先令
S 为空,顺序遍历每个b_i 。 -
如果
b_i=0 ,直接跳过它。 -
否则如果
S 为空或者S 最后一个下标的奇偶性与i 不同,将i 加入到S 中,其它情况跳过。
我们声称,重复此过程确定每次操作选择的子序列,即可使答案取到下界,下面给出证明。
令
首先要观察到,每对
一个重要的结论是,
可以发现的是,此时
如果
如果
综上,我们说明了这种贪心策略能使答案取到下界。
官方题解在证明过程中写到
\forall (l,r)\in T 还有r\in S 成立,笔者认为这是错误的,考虑b=\{-3,0,-3\} ,则显然T=\{(1,3)\} 且S=\{1\} 。如果确为官方题解笔误或者是我的理解错误,请您在评论区指出/bx/bx/bx。
因此对于整个序列
这里使用了单调栈实现,时间复杂度
#include<bits/stdc++.h>
#define int long long
#define For(i, a, b) for(int i = (a); i <= (b); i++)
#define Rof(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
int n, a[N], b[N];
int top, ans, st[N], L[N], R[N];
inline void add(int &x, int y){x += y; if(x >= mod) x -= mod;}
inline void sub(int &x, int y){x += mod - y; if(x >= mod) x -= mod;}
void Solve(){
cin >> n;
For(i, 1, n) cin >> a[i];
For(i, 1, n){
if(i & 1) b[i] = b[i - 1] + a[i];
else b[i] = b[i - 1] - a[i];
}
top = ans = 0;
For(i, 1, n) R[i] = n;
For(i, 1, n){
while(top && b[st[top]] < b[i]) R[st[top]] = i - 1, top--;
L[i] = !top ? 0 : st[top] + 1; st[++top] = i;
}
For(i, 1, n) (ans += (R[i] - i + 1) * (i - L[i] + 1) % mod * (b[i] % mod) % mod) %= mod;
top = 0;
For(i, 1, n) R[i] = n;
For(i, 0, n){
while(top && b[st[top]] >= b[i]) R[st[top]] = i - 1, top--;
L[i] = !top ? 0 : st[top] + 1; st[++top] = i;
}
For(i, 1, n) (ans -= (R[i] - i + 1) * (i - L[i] + 1) % mod * (b[i] % mod) % mod) %= mod;
ans = (ans % mod + mod) % mod;
cout << ans << '\n';
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
int T = 1; cin >> T;
while(T--) Solve();
return 0;
}