2217: [Poi2011]Lollipop
Time Limit: 15 Sec Memory Limit: 64 MBSec Special JudgeSubmit: 383 Solved: 159
[Submit][Status][Discuss]
Description
有一个长度为n的序列a1,a2,...,an。其中ai要么是1("W"),要么是2("T")。
现在有m个询问,每个询问是询问有没有一个连续的子序列,满足其和为q。
Input
第一行n,m (1<=n,m<=1000000)
第二行这个序列,起始编号为1,终止编号为n
下面每行一个询问q,询问有没有一个连续的子序列,满足其和为q (1<=q<=2000000)
Output
对于每个询问,输出一行,如果有,输出这个序列的起点和终点(如果有多个输出任意一个);如果没有,输出“NIE”。
Sample Input
TWTWT
5
1
7
Sample Output
2 2
NIE
HINT
尚无SPJ,请不要提交
这题有一个性质,如果存在一个连续的序列和为k,那么在前缀和中一定存在k或者k+1
为什么?
可以证明,如果l-r和为k,那么后面部分,可以不断减去,前面部分不断加入,如果相差为2,那么后面部分减去一个1,或者2,使其
差<2就可以了,这样是保证了这个性质。
所以对于这道题,对于k判断前缀和十分有k,有的话直接输出,否则判断是否有k+1,如果有的话,就记录前面二的个数,后面哪个位置是1,
然后搞一搞就好了。
1 #pragma GCC optimize(2) 2 #pragma G++ optimize(2) 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdio> 7 #include<cstring> 8 9 #define N 27 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 #define MAXN 1000010 20 #define MAXM 1010 21 #define INF 1000000000 22 #define MOD 1000000007 23 #define eps 1e-8 24 #define ll long long 25 26 int n,m; 27 char a[MAXN]; 28 int s[MAXN],nxt[MAXN]; 29 int v[MAXN<<1]; 30 int main() 31 { 32 int i,x; 33 scanf("%d%d%s",&n,&m,a+1); 34 for(i=1;i<=n;i++) 35 { 36 s[i]=s[i-1]+1+(a[i]=='T'); 37 v[s[i]]=i; 38 } 39 x=n+1; 40 for(i=n;i;i--) 41 { 42 if(a[i]=='W')x=i; 43 nxt[i]=x-i; 44 } 45 while(m--) 46 { 47 scanf("%d",&x); 48 if(v[x])printf("%d %d\n",1,v[x]); 49 else if(v[x+1]) 50 { 51 int l=1,r=v[x+1]; 52 if(nxt[l]<nxt[r]) 53 { 54 r+=nxt[l]; 55 l+=nxt[l]+1; 56 printf("%d %d\n",l,r); 57 }else if(r+nxt[r]<=n) 58 { 59 l+=nxt[r]; 60 r+=nxt[r]; 61 printf("%d %d\n",l,r); 62 }else printf("NIE\n"); 63 }else printf("NIE\n"); 64 } 65 }