0%

思路讲解

【Codeforces Round 1024 (Div. 2) 题目讲解 ABCDE (CF2102)】 【精准空降到 16:30】 https://www.bilibili.com/video/BV1CFELzVExf/?p=5&share_source=copy_web&vd_source=6ca0bc05e7d6f39b07c1afd464edae37&t=990

这场的E题,用到了一个技巧,就是2,2,3,4 → 1,2,3,4 这如何利用set就能做到(维护一个序列,要求 aiia_i≥ i ,然后给你一堆数,要求你能够最长化这个序列)?其实可以换个思路,初始的 set 里有 1,2,3,4,5 然后删。

具体见CF-1024-E. 23 Kingdom

CF-1028-D. Gellyfish and Camellia Japonica(直接构造等于难,构造最小的大于等于)

https://www.luogu.com.cn/article/rae0b6wl

总结的话,主要的启发就是把 构造使得与目标相等 转换成 最小的构造使得大于等于目标

介绍

消除后效性,狭义上指的是dp,但广义上来说,贪心做法等也有时需要考虑后效性问题。

总体而言,只要你是想要把一个问题拆开来分析求解,那么合起来的时候,就要考虑后效性了。

案例分析

CF-1024-D. Quartet Swapping(四重交换) 这个是解决了交换数量要保持相同,但是最优情况可能无法保持相同,如何找到次优情况呢?或者说什么发现该情况只适用于次优情况呢?涉及冒泡排序以及逆序对。

2025金马高校联赛-B战术单元协同训练 利用链表来消除后效性

Edu-179-E. Changing the String 在线处理比较难,需要考虑对后续操作的影响,可以采用离线方法处理,因为下标小的。

思路讲解

不难注意到,你所选择的区间之中,不允许出现两个区间相离的情况。

image

因为这两个区间如果变为相交的话,贡献的答案值一定更大。

由这个结论,那么新加入的区间的 右端点>以前的所有左端点右端点>以前的所有左端点,并且 左端点<以前的所有右端点左端点<以前的所有右端点,因此,所有的左右端点就会分居两端,因为起始的 右端点>左端点右端点>左端点,新加入的 右端点>以前的所有左端点右端点>以前的所有左端点,左端点反之亦然。

image

那么贪心地,我们其实就是想让 il\sum{i_l} 最小, ir\sum{i_r} 最大,那么左端点只要贪心地选择下标小的,右端点我们只要贪心地选择下标大的。

最后一个问题,就是当我们拿到一个序列,如 22342,2,3,4,我们如何知道他是否可以映射到12341,2,3,4 只通过减法。

那么这个其实有一个小的 trick,如果说用加入元素的方法判断,大抵是要用到树状数组或者线段树,但如果使用删除的方法,就可以只用 set 实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
set<ll> st;
auto init=[&](){ // 初始化函数
st.clear();
FOR(i,0,N+1){
st.insert(i);
}
};
auto proc=[&](ll x){ // 处理函数
auto it=st.upper_bound(x);
--it;
if(*it==0){
return false;
}else{
st.erase(it);
return true;
}
};

AC代码

https://codeforces.com/contest/2101/submission/319792559

心路历程(WA,TLE,MLE……)

其实我们的要求是没有任意两个区间相离,这个用线段树判断是有点问题的。

一个比较好的近似解

1
2
3
4
5
6
hack:
1
10
1 1 2 2 3 3 4 4 5 5
ans:
18

https://codeforces.com/contest/2101/submission/319732582

思路讲解

那么注意到,在该操作过程中,一个数下标的的奇偶性是不会发生变化的。
还有一个比较隐秘的不变量就是偶数下标的反转数和奇数下标的反转数是相同的,因为每次交换相邻偶数下标时, 会迫不得己地同时交换奇数下标,反之亦然。

那么要用到我们观察出来的第二个性质,就是偶数下标的反转数和奇数下标的反转数是相同的,那么如果说偶数下标序列和奇数下标序列的逆序对数量的奇偶性不相同(逆序对数量其实也就是需交换操作数量,因为本道题目是只能相邻交换,相当于冒泡排序),那么就说明必须要牺牲一个不反转(或者有时是在有序的基础上,再多反转一个,反正无论是 +1+1 还是 1-1 以后奇偶性一定就相同了)。

那么应该反转哪个最优呢?不难发现这样交换最优。

1
2
3
if((revOdd-revEven)%2!=0){
swap(Ans[N],Ans[N-2]);
}

AC代码

https://codeforces.com/contest/2101/submission/319512581

心路历程(WA,TLE,MLE……)

思路讲解

从外往里转会好很多。

image

AC代码

https://codeforces.com/contest/2102/submission/319351416

心路历程(WA,TLE,MLE……)

从里往外转比较烦。

WA