题意:给一个长度为 n n n的只有 1 1 1和 2 2 2的序列,多次询问给定 x x x构造或判断无法构造一个区间和为 x x x
注意到 1 1 1和 2 2 2实质上是改不改变奇偶性,所以往这上面考虑
我们发现如果一个区间 [ L , R ] [L,R] [L,R]和为 x ( x > 2 ) x(x>2) x(x>2),我们就可以构造出 x − 2 x-2 x−2。方法是如果端点有 2 2 2把这个 2 2 2去掉,否则两边都是 1 1 1,把两边都去掉。
也就是说,如果 x x x可以构造,那么小于 x x x的奇偶性相同的正整数都可以构造出。
那我们只需要对奇数和偶数分别找出最大的即可。
显然 [ 1 , n ] [1,n] [1,n]是其中一个。
然后找到离端点最近的 1 1 1,整体挖掉就可以改变奇偶性,显然是最大的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 2000005
using namespace std;
int l[MAXN],r[MAXN];
char s[MAXN];
int a[MAXN];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
int sum=0;
for (int i=1;i<=n;i++) sum+=(a[i]=1+(s[i]=='T'));
l[sum]=1,r[sum]=n;
int k1=0,k2=0;
while (a[k1+1]==2) ++k1;
while (a[n-k2]==2) ++k2;
if (k1<n-1||k2<n-1)
{
if (k1<k2) l[sum-2*k1-1]=k1+2,r[sum-2*k1-1]=n;
else l[sum-2*k2-1]=1,r[sum-2*k2-1]=n-k2-1;
}
for (int i=sum;i>=3;i--)
{
if (!l[i]) continue;
if (a[l[i]]==2) l[i-2]=l[i]+1,r[i-2]=r[i];
else
if (a[r[i]]==2) l[i-2]=l[i],r[i-2]=r[i]-1;
else l[i-2]=l[i]+1,r[i-2]=r[i]-1;
}
while (m--)
{
int x;
scanf("%d",&x);
if (!l[x]) puts("NIE");
else printf("%d %d\n",l[x],r[x]);
}
return 0;
}