传送门:CF
[前题提要]:无.
先考虑
D
1
D1
D1.把玩一下题意就不难发现取了一根棒之后,后面的所有都是往前移一格,也就是后缀的贡献此时贡献乘上了一个
−
1
-1
−1.
然后我们想一下我们取了一根棒之后对整体会发生什么.
不妨假设我们的区间是
[
l
,
r
]
[l,r]
[l,r],取的棒是
p
o
s
pos
pos位置,显然这根棒的贡献可以是
1
,
−
1
1,-1
1,−1(注意,此时指的是贡献,而不单单只是值).我们假设棒之前的贡献为
x
x
x,后缀贡献是
y
y
y.刚开始的贡献和为
z
z
z.不妨假设此时是最后一次拿棒.那么此时就有
x
+
1
+
y
=
z
x+1+y=z
x+1+y=z
z
−
1
−
2
∗
y
=
0
z-1-2*y=0
z−1−2∗y=0或者
x
−
1
+
y
=
z
x-1+y=z
x−1+y=z
z
+
1
−
2
∗
y
=
0
z+1-2*y=0
z+1−2∗y=0解一下上述两个方程组,就会发现我们的
x
=
y
=
z
−
1
2
或者
x
=
y
=
z
+
1
2
x=y=\frac{z-1}{2}或者x=y=\frac{z+1}{2}
x=y=2z−1或者x=y=2z+1但是是有限制条件的,前者需要保证取的贡献为
1
1
1,后者需要保证取的贡献为
−
1
-1
−1.
诶,此时会发现如果我们最后的
z
z
z是奇数的话,会发现,我们总是能找到一个
x
,
y
x,y
x,y,因为此时他们的取值小于
z
z
z(这里不是非常严谨,但是先按下不表),并且每次贡献和的差不会超过1.但是这对吗?我们似乎还要保证后面那一位的贡献才对.
考虑对
z
z
z进行分类讨论:
假设此时的
z
z
z是正奇数,那么此时,我们不妨画出下列贡献和变化图像:
你会发现,如果我们找第一个等于
z
−
1
2
+
1
\frac{z-1}{2}+1
2z−1+1的点,我们总能保证该点的贡献为1,且前缀贡献为
z
−
1
2
\frac{z-1}{2}
2z−1,为什么呢,因为我们找的点是第一个到达此位置的点,说明之前没有任意一个点在这个点的上方,因为他们都是从小往大增加的,所以该点此时必然是最大值,所以必然为1.
需要格外注意的是,此时对于另外一种情况,也就是找第一个
z
+
1
2
−
1
\frac{z+1}{2}-1
2z+1−1的点,此时我们就无法保证该情况的正确性了,因为第一个该值的点不可能使
−
1
-1
−1,如果我们找第二个点,那么此时的维护方式就比价麻烦.
对于负数情况,我们同样可以得出,找一个等于 z + 1 2 − 1 \frac{z+1}{2}-1 2z+1−1的点必然满足情况,因为方法同上,此处就不在赘述了.
此时,我们就可以得出,对于初始贡献为奇数的情况,我们都可以通过修改一个点来将其改为0.那么对于偶数我们该怎么办呢.首先需要注意的是,我们最后的序列必然是一个偶数序列,因为对于一个序列来说,我们将其两个两个分组,会得到 11 , 10 , 01 , 00 11,10,01,00 11,10,01,00这四种贡献组合,贡献分别为 0 , 2 , − 2 , 0 0,2,-2,0 0,2,−2,0,是偶数贡献的,所以如果是奇数,最后必然不可能变成0.所以对于偶数情况,我们的操作次数必然大于等于2.因此,我们大可以花一费将偶数改为奇数,然后奇数情况可以再花一费变成0(这个部分在上述仔细讨论过了),所以此时操作数为2.
下面是具体的代码部分( h a r d v e r s i o n hard\;version hardversion):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls (rt<<1)
#define rs (rt<<1|1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
//inline void print(__int128 x){
// if(x<0) {putchar('-');x=-x;}
// if(x>9) print(x/10);
// putchar(x%10+'0');
//}
#define maxn 1000000
const double eps=1e-8;
#define int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int sum[maxn];vector<int>v[maxn];int a[maxn];
int main() {
cin.sync_with_stdio(false);cin.tie();cout.tie();
int T;cin>>T;
while(T--) {
int n,q;cin>>n>>q;
string s;cin>>s;s=" "+s;
v[n].push_back(0);
for(int i=1;i<=n;i++) {
if(s[i]=='+') sum[i]=sum[i-1]+1*pow(-1,i-1),a[i]=1;
else sum[i]=sum[i-1]-1*pow(-1,i-1),a[i]=-1;
v[sum[i]+n].push_back(i);
}
for(int i=1;i<=q;i++) {
int l,r;cin>>l>>r;
int base=-1;
if(l&1) base=1;
if((r-l+1)&1) {
cout<<1<<endl;
int z=(sum[r]-sum[l-1])*base;
int temp;
if(z<0) temp=(z-1)/2;
else temp=(z+1)/2;
int num=sum[l-1]+base*temp;
auto pos=lower_bound(v[num+n].begin(),v[num+n].end(),l);
if(pos!=v[num+n].end()) {
cout<<*pos<<endl;
}
}
else {
if(sum[r]-sum[l-1]==0) {
cout<<0<<endl;
}
else {
cout<<2<<endl;
cout<<r<<" ";
r--;
int z=(sum[r]-sum[l-1])*base;
int temp;
if(z<0) temp=(z-1)/2;
else temp=(z+1)/2;
int num=sum[l-1]+base*temp;
auto pos=lower_bound(v[num+n].begin(),v[num+n].end(),l);
if(pos!=v[num+n].end()) {
cout<<*pos<<endl;
}
}
}
}
for(int i=0;i<=2*n;i++) v[i].clear();
}
return 0;
}