D1T1
这也是题?
D2T1
考虑挖掘题目的性质。容易发现:
当序列中出现 110 时,设其中 0 的下标为 ,答案就是所有 110 的 的最大值。特别地,如果序列中没有 110,但是出现了 101,那么答案为 1。
又因为要支持区间取反,于是我们可以搞一棵线段树,维护:
-
区间左右端点与长度
-
区间 110 出现位置
-
区间 001 出现位置
-
区间是否出现 101
-
区间是否出现 010
-
区间取反 tag
-
区间首两个元素和末两个元素
然后相邻两个区间信息合并就是把原来的算上,再考虑两个区间相邻的边界会不会出现新的某特定串。
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 28 29 30 31 32 33 34 35 36 37
| inline node merge(node L,node R){ node ret; ret.len = L.len+R.len; ret.st1 = L.st1; if(L.len>1)ret.st2=L.st2;else ret.st2=R.st1; ret.ed2 = R.ed2; if(R.len>1)ret.ed1=R.ed1;else ret.ed1=L.ed2; ret.l=L.l; ret.r=R.r; ret.app101 = L.app101 || R.app101; ret.app010 = L.app010 || R.app010; ret.pos110 = min(L.pos110,R.pos110); ret.pos001 = min(L.pos001,R.pos001); static int tmp[6],pos[6]; int v=0; if(L.len>1)tmp[v++]=(L.ed1),pos[v-1]=(L.r-1); tmp[v++]=(L.ed2),pos[v-1]=(L.r); tmp[v++]=(R.st1),pos[v-1]=(R.l); if(R.len>1)tmp[v++]=(R.st2),pos[v-1]=(R.l+1); if(v<=2)return ret; auto chk = [&](int st,int x,int y,int z){ return tmp[st]==x && tmp[st+1]==y && tmp[st+2]==z; }; ret.app101 |= chk(0,1,0,1); ret.app010 |= chk(0,0,1,0); if(chk(0,1,1,0))chkMin(ret.pos110,pos[2]); if(chk(0,0,0,1))chkMin(ret.pos001,pos[2]); if(v<=3)return ret; ret.app101 |= chk(1,1,0,1); ret.app010 |= chk(1,0,1,0); if(chk(1,1,1,0))chkMin(ret.pos110,pos[3]); if(chk(1,0,0,1))chkMin(ret.pos001,pos[3]); return ret; }
|
然后修改某个节点就是把记录的相对应的东西交换一下,并对记录的首尾四个元素取反。
D1T2
考虑操作的方式。我们不妨把每次操作中较小的那个元素向较大的元素连边,易得每个节点至多只有一条出边,且不会形成环。(请不要对相邻的 0 和 0 做无谓的操作!)
于是可以想象,操作完成后,一个序列由若干个形如下图的东西组成:
以下将形如此状的 称为 top。
第一问
接下来讨论第一问。
我们考虑可以把序列划分成段,每段按照上述形状计算出段内最大值。设 为以 结尾,前面部分的最大值。有转移方程:
然后考虑在 的复杂度内预处理出 。
对于每个左端点,我们预处理出他能贡献到的最远的 top ,右端点同理预处理出 。
这样子对于每个询问,端点只会在区间 之中。
考虑什么样的点能成为 top。
对于一段区间,我们考虑每个数对 top 的贡献。容易发现与 top 距离为偶数的点有正贡献,否则有负贡献。
那么我们计算区间 的值。
-
当 时,显然任意位置上的数都可以作为 top。
-
当 时,这意味着最后有数残余,且残余那一位系数为正,因为只有残余的那一位可以作为 top,所以 top 一定在 的点位上,即奇数下标点位。
-
当 时,这意味着最后有数残余,且残余那一位系数为负,top 一定在 的点位上,即偶数下标点位。
当 时,无论 top 怎么选最后整段区间都会变成 ,于是这段区间的 就是区间 的和。
否则,top 位置无法造成贡献,这段区间的 就是区间 的和减去 top 处的 。我们想最大化贡献,就得最小化 top 处贡献,于是在 top 可取区间内找到满足下标限制的 最小值即可。注意 top 是有奇数下标或偶数下标限制的,因此要对两种下标分别预处理区间 min,这个可以直接暴力 处理。
另外,【某数没有被进行操作】可以通过 的情况转移(以下第二问也是如此)。
第二问
以上我们做完了第一问,到了第二问,我们沿用第一问的思路,但是你会发现形似 的区间会有 或 等多种表现方式,我们不妨规定:在计算之前的【最远左右端点】时对于能消为 0 的不再扩展。
如此便处理完了大多数情况,避免算重,但是你会发现对于 且 的区间上述做法不会统计下来,但是这恰恰是我们需要统计的最小单元,于是特判一下即可。
剩下的就和以前的做法差不多了:我们设 为截止下标 ,题目所求式子的值。有转移方程:
其中 。
然后对于 的计算,我们考虑先处理出区间 中 的乘积(设为 )。
沿用第一问时的 。
对于一个 top 下标为 ,其答案即为 。
那么我们对每个点位的 的逆元进行前缀和(同样也要分两种下标进行)。
然后设 top 可行区间中满足下标条件的点位的逆元之和为 ,那么 就是 。
如此,我们做完了这道题目。