bzoj 2217 Lollipop

题目大意:

有一个长度为n的序列a1,a2,...,an。其中ai要么是1("W"),要么是2("T")

现在有m个询问,每个询问是询问有没有一个连续的子序列,满足其和为q

思路:

因为序列中只有1和2

所以一定存在一个前缀和等于x或x-1

当前缀和等于x直接输出即可

若等于x-1 则可以建一个r数组存储向后延伸有多少个连续的2

这样可以将这一段前缀和向后移

如果r 1较小 直接右移

否则向右移使右侧+1

具体可以手画来推

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 2001000
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,T,hsh[MAXN],s[MAXN],r[MAXN]; 
21 char ch[MAXN];
22 int main()
23 {
24     n=read(),T=read();scanf("%s",ch+1);
25     for(int i=1;i<=n;i++) s[i]=s[i-1]+((ch[i]=='W')?1:2),hsh[s[i]]=i;
26     int tmp=n+1,x,k;
27     for(int i=n;i;i--) {if(ch[i]=='W') tmp=i,k=i;r[i]=tmp-i;}
28     while(T--)
29     {
30         x=read();
31         if(x==1) printf("%d %d
",k,k);
32         else if(hsh[x]) printf("%d %d
",1,hsh[x]);
33         else if(hsh[x-1])
34         {
35             if(r[hsh[x-1]+1]>r[1]) printf("%d %d
",2+r[1],hsh[x-1]+r[1]+1);
36             else if(r[hsh[x-1]+1]+hsh[x-1]+1<=n) printf("%d %d
",1+r[hsh[x-1]+1],hsh[x-1]+r[hsh[x-1]+1]+1);
37             else puts("NIE");
38         }
39         else puts("NIE");
40     }
41 }
View Code

网上的大佬好像都是用的前缀和x+1 大概会方便一些?

原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8444295.html