题解
一番研究发现:
我们可以先找出可以表示出的值最大的奇数和偶数。
那么小于等于该数的所有奇数/偶数均可以表示出来。
一个简单的说明:
假设现在表示出的最大偶数为n(n>=4)(n=2就只有一个2,没法表示其它的了QAQ),可以表示的范围为l-r,那么考虑三种情况:
1.两端均为2,那么任意移动一端向内一格
2.一端为2,一端为1,移动为2的一端向内一格
3.两端均为1,那么两端都向内移动一格
这样操作直到区间长度为1,达到表示的最小的1或2。
所以对询问降序排序一波,离线处理就好了。
妙啊,本蒟蒻没有想到QWQ
代码
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=1e6+10;
char s[N];
int n,m,a[N],even,odd,st,ed,sum;
int le,re,lo,ro,ansl[N],ansr[N];
struct P{int id,v;}t[N];
bool cmp(const P&x,const P&y){return x.v>y.v;}
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline void mk()
{
if(sum&1){
lo=1;ro=n;
odd=sum;
if(st==ed && st){
if(st-1 > n-st){
even=2*(st-1);
le=1;re=st-1;
}else{
even=2*(n-st);
le=st+1;re=n;
}
}else if(st){
if(st-1 < n-ed){
even=sum-(2*(st-1)+1);
le=st+1;re=n;
}else{
even=sum-(2*(n-ed)+1);
le=1;re=ed-1;
}
}
}else{
even=sum;
le=1;re=n;
if(st){
if(st-1 < n-ed){
odd=sum-(2*(st-1)+1);
lo=st+1;ro=n;
}else{
odd=sum-(2*(n-ed)+1);
lo=1;ro=ed-1;
}
}
}
}
int main(){
int i,j;n=rd();m=rd();
scanf("%s",s+1);
for(i=1;i<=n;++i) {
a[i]= s[i]=='W'? 1:2;
sum+=a[i];
if(a[i]==1) !st? ed=st=i:ed=i;
}
mk();
for(i=1;i<=m;++i) t[i].v=rd(),t[i].id=i;
sort(t+1,t+m+1,cmp);
for(i=1;i<=m;++i){//n->m
if(t[i].v&1 && (!lo || t[i].v>odd)) ansl[t[i].id]=-1;
else if(!(t[i].v&1) && (!le || t[i].v>even)) ansl[t[i].id]=-1;
else if(t[i].v&1){
while(odd>t[i].v){
if(a[lo]==2) lo++;else if(a[ro]==2) ro--;
else{lo++;ro--;}odd-=2;
}
ansl[t[i].id]=lo;ansr[t[i].id]=ro;
}else{
while(even>t[i].v){
if(a[le]==2) le++;else if(a[re]==2) re--;
else{le++;re--;}even-=2;
}
ansl[t[i].id]=le;ansr[t[i].id]=re;
}
}
for(i=1;i<=m;++i) ansl[i]==-1? printf("NIE\n"):printf("%d %d\n",ansl[i],ansr[i]);
}