题目大意:
有一个长度为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\n",k,k); 32 else if(hsh[x]) printf("%d %d\n",1,hsh[x]); 33 else if(hsh[x-1]) 34 { 35 if(r[hsh[x-1]+1]>r[1]) printf("%d %d\n",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\n",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 }
网上的大佬好像都是用的前缀和x+1 大概会方便一些?