题目思路
由D1观察可以发现
对于奇数长度链 消去一个值一定可满足题意 对于偶数链 如果当前满足题意则跳过 如果不满足题意则消去两个值时一定可以满足题意
根据这个规律我们再去做D2
sum【i】代表 a1−a2+a3−a4+…的前缀和
当目前为偶数链且 已经满足题意时 直接输出0
当目前为奇数链时 我们需要找到一个 i 满足去掉这个下标为 i 的值以后
sum[i-1]-sum[l-1]=sum[r]-sum[i] 移项为
sum[i-1]+sum[i]=sum[r]+sum[l-1]
当目前为偶数链且不符合题意时
任意输出一个位置 后将情况转化为奇数链进行运算
对于每一种sum[i-1]+sum[i]的值在预处理时用vector进行存储
用vector存储这一块学习了这位大佬代码
对于每一次询问 l,r 用二分找到适合的下标 输出
ps 另外这个题时间卡得很死 去掉了很多memset 和优化了输入输出以后才跑了1996ms压线过
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
int t,n,q;
int sum[maxn];
int sum2[maxn];
map<int ,vector<int > >a;
void init()
{
a.clear();
//memset(sum,0,sizeof sum);
//memset(sum2,0,sizeof sum2);
}
int sol(int l,int r)
{
int now=sum[r]+sum[l-1];
int tp=lower_bound(a[now].begin(),a[now].end(),l)-a[now].begin();
return a[now][tp];
}
int main()
{
cin>>t;
//int tmp=1e6;
//while(tmp--);
while(t--)
{
scanf("%d %d",&n,&q);
init();
int x,y;
char s[maxn];
scanf("%s",s);
for(int i=1;i<=n;i++)
{
if(s[i-1]=='+')
x=1;
else x=-1;
y=x;
if(i%2==0)
{
x*=-1;
}
else y*=-1;
sum[i]=0;
sum[i]+=sum[i-1]+x;
a[sum[i]+sum[i-1]].push_back(i);
//sum2[i]+=sum2[i-1]+y;
}
while(q--)
{
cin>>x>>y;
if((y-x+1)%2==1)
{
printf("1\n%d\n",sol(x,y));
continue;
}
if(sum[y]-sum[x-1]==0)
{
printf("0\n");
}
else
{
printf("2\n%d %d\n",x,sol(x+1,y));
}
}
}
return 0;
}