Description
Solution
很难想到啊。。
对于一个和为(X)的串(S),注意到我们总能构造出一个长度更小的(S')满足(X'=X-2)。
即,设(S=s[lsim{r}]),若(s[l]==s[r]=='W'),就(l++,r--)。
否则设(s[l]=='T'),直接(l++)即可。
所以按照子串和的奇偶性分类,依次构造就可以了。问题是如何找出某一奇偶性的(S)中,(X)最大,且(|S|)尽量大的初始串。
其实,这个串一定是(s[1sim{i}])或者(s[isim{n}])。
证明:如果(S=s[lsim{r}](l eq1,r eq{n})),若(s[l-1]=='T'lor{[r+1]=='T'}),总可以使(l--lor{r++}),从而(|S|)变大且不会影响奇偶性。
如果(x>p[x\%2])就输出NIE
。
Code
#include <bits/stdc++.h>
using namespace std;
int n, m, l1, r1, l2, r2, s[1000005], p[2], rl[2000005], rr[2000005];
char ch[1000005];
int read()
{
int x = 0, fl = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
return x * fl;
}
void check(int l, int r)
{
int now = s[r] - s[l - 1];
if (now >= p[now % 2])
{
p[now % 2] = now;
if (now % 2 && r - l > r1 - l1) {l1 = l, r1 = r;}
if (now % 2 == 0 && r - l > r2 - l2) {l2 = l, r2 = r;}
}
return;
}
int main()
{
n = read(), m = read();
scanf("%s", ch + 1);
for (int i = 1; i <= n; i ++ )
s[i] = s[i - 1] + ((ch[i] == 'T') ? 2 : 1);
for (int i = 1; i <= n; i ++ ) check(1, i);
for (int i = 1; i <= n; i ++ ) check(i, n);
int now = p[1];
while (now >= 1)
{
rl[now] = l1, rr[now] = r1;
if (ch[l1] == 'W' && ch[r1] == 'W') {l1 ++ , r1 -- ;}
else
{
if (ch[l1] == 'T') l1 ++ ;
else r1 -- ;
}
now -= 2;
}
now = p[0];
while (now >= 2)
{
rl[now] = l2, rr[now] = r2;
if (ch[l2] == 'W' && ch[r2] == 'W') {l2 ++ , r2 -- ;}
else
{
if (ch[l2] == 'T') l2 ++ ;
else r2 -- ;
}
now -= 2;
}
while (m -- )
{
int x = read();
if (x > p[x % 2])
{
puts("NIE");
continue;
}
printf("%d %d
", rl[x], rr[x]);
}
return 0;
}