给你一个长度为 n n n的串, + + +代表 1 1 1, − - −代表 − 1 -1 −1,让后有 q q q个询问,每次询问 [ l , r ] [l,r] [l,r]区间,将这段区间的数拿出来,设为 a [ 1 , r − l + 1 ] a[1,r-l+1] a[1,r−l+1],算 a 1 − a 2 + a 3 − . . . = x a_1-a_2+a_3-...=x a1−a2+a3−...=x,问最少删去多少个数才能使得 x x x为 0 0 0,输出删的数的位置。
n , q ≤ 3 e 5 n,q\le3e5 n,q≤3e5
首先考虑简单版本,就是不要求输出删的位置,只考虑删多少。
每次询问拿出来的区间,奇偶位置符号分别乘 1 , − 1 1,-1 1,−1,不难发现我们将 − 1 , 1 -1,1 −1,1倒过来也是没有影响的,也就是偶奇分别乘 1 , − 1 1,-1 1,−1。
那么既然拿出来的区间对位置奇偶没影响,那么我们考虑一开始就处理一个 a [ i ] a[i] a[i]表示第 i i i个位置的数,再维护个前缀和 s u m [ i ] sum[i] sum[i],我们现在能得到 [ l , r ] [l,r] [l,r]的和了,考虑如何计算答案。
( 1 ) (1) (1)如果当前区间和是 0 0 0,那么答案显然为 0 0 0。
( 2 ) (2) (2)如果当前区间和为奇数,那么一定可以找到一个位置,去掉当前位置后区间和为 0 0 0。
( 3 ) (3) (3)如果当前区间和为偶数,那么我们可以把 l l l的位置删掉,这样区间和一定变为奇数,让后再按照 ( 2 ) (2) (2)来找一个位置去掉即可。
所以如果是 e a s y easy easy版本的话,分以上三种讨论即可。
考虑如果要求输出位置怎么办。
对于 ( 1 ) (1) (1),直接输出 0 0 0即可。
对于 ( 2 ) (2) (2),由于其一定存在一个位置去掉后区间和为 0 0 0,考虑什么位置去掉是合法的呢?假设我们去掉的位置是 p o s pos pos,那么 [ l , p o s − 1 ] , [ p o s + 1 , r ] [l,pos-1],[pos+1,r] [l,pos−1],[pos+1,r]两个区间的和原本是相同的,也就是 s u m [ l , p o s − 1 ] = s u m [ p o s + 1 , r ] sum_{[l,pos-1]}=sum_{[pos+1,r]} sum[l,pos−1]=sum[pos+1,r],那么我们去掉 p o s pos pos位之后,前面的不变,后面的值全部取反,也就是 s u m [ l , p o s − 1 ] = − s u m [ p o s + 1 , r ] sum_{[l,pos-1]}=-sum_{[pos+1,r]} sum[l,pos−1]=−sum[pos+1,r],也就是说我们找到这样的一个合法位置即可。
考虑怎么找呢?显然可以二分来找,二分位置,有点小繁琐,我们考虑一种更加妙的方式。
我们给每个 s u m [ i ] + s u m [ i − 1 ] sum[i]+sum[i-1] sum[i]+sum[i−1]开一个桶,存下来 i i i这个位置,考虑当前询问区间为 [ l , r ] [l,r] [l,r]。你那么我们找到 s u m [ l − 1 ] + s u m [ r ] sum[l-1]+sum[r] sum[l−1]+sum[r]对应的桶里的某个位置 x x x,那么现在有 s u m [ r ] + s u m [ l − 1 ] = s u m [ x ] + s u m [ x − 1 ] sum[r]+sum[l-1]=sum[x]+sum[x-1] sum[r]+sum[l−1]=sum[x]+sum[x−1],移项得 s u m [ r ] − s u m [ x ] = s u m [ x − 1 ] − s u m [ l − 1 ] sum[r]-sum[x]=sum[x-1]-sum[l-1] sum[r]−sum[x]=sum[x−1]−sum[l−1],不难发现,如果我们将 x x x这个位置去掉后,那么前后两个区间的和就为 0 0 0了,所以我们只需要在 s u m [ i ] + s u m [ i − 1 ] sum[i]+sum[i-1] sum[i]+sum[i−1]的桶内二分一个位置即可,由于保证一定有解,所以一定存在这样的一个位置。
对于 ( 3 ) (3) (3),删掉 l l l位置,将其变为奇数,让后进行 ( 2 ) (2) (2)即可。
// Problem: D1. Two Hundred Twenty One (easy version)
// Contest: Codeforces - Codeforces Round #741 (Div. 2)
// URL: https://codeforces.com/contest/1562/problem/D1
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const int N=2000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,q;
int a[N],sum[N];
vector<int>v[N];
char s[N];
int get(int l,int r) {
int now=sum[l]+sum[r]+2*n;
int pos=lower_bound(v[now].begin(),v[now].end(),l+1)-v[now].begin();
return v[now][pos];
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
int _; scanf("%d",&_);
while(_--) {
scanf("%d%d%s",&n,&q,s+1);
for(int i=1;i<=n;i++) {
if(s[i]=='-') {
if(i%2==1) sum[i]=sum[i-1]-1;
else sum[i]=sum[i-1]+1;
}
else {
if(i%2==1) sum[i]=sum[i-1]+1;
else sum[i]=sum[i-1]-1;
}
}
for(int i=1;i<=n;i++) v[sum[i]+sum[i-1]+2*n].pb(i);
while(q--) {
int l,r; scanf("%d%d",&l,&r);
int now=abs(sum[r]-sum[l-1]);
if(now==0) puts("0");
else if((r-l+1)%2==1) {
puts("1");
printf("%d\n",get(l-1,r));
} else {
puts("2");
printf("%d %d\n",l,get(l,r));
}
}
for(int i=1;i<=n;i++) v[sum[i]+sum[i-1]+2*n].clear();
}
return 0;
}
/*
1
14 3
+--++---+++---
1 14
6 12 ---+++- -1 1 -1 -1 1 -1 -1
3 10
2
1 5
1
12
0
*/