D - Repeated Sequence
思路:先存储数组的前缀和,把周期的和剪掉,这样就只需要查找在一个周期是否满足,枚举1-n,毕竟不确定周期是从哪开始的,对于从当前数为起始的周期,当剩余的数res小于从当前i为起点的i后缀和时,我们只需要查找一个R 满足b[r]-b[i-1]区间和等于res,若最后查找的r不满足说明就不存在,反之当大于从当前i为起点的i后缀和说明还需要前i的一个X前缀和。需要满足b[x]+b[n]-[i-1]=res。(别忘了判断最后查找的X是否满足哦,因为这里查找的R和X都是>=res的最小下标,毕竟比R,X再大只会越来越大于res)。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL a[200010],b[200010],n,s,res,flag=0;
bool check(int x,int y)
{
if(b[x]-b[y-1]>=res) return true;
else return false;
}
bool check1(int x,int y)
{
if(b[n]-b[y-1]+b[x]>=res) return true;
else return false;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>s;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]+=b[i-1]+a[i];
}
LL cnt=s/b[n];
res=s-b[n]*cnt;
if(res==0) flag=1;
for(int i=1;i<=n;i++)
{
// 当前i为周期起点,后缀和>=res
if(b[n]-b[i-1]>=res)
{
int l=i-1,r=n+1;
while(l+1<r){
int mid=(l+r)>>1;
if(check(mid,i)) r=mid;
else l=mid;
}
if(b[r]-b[i-1]==res)
{
flag=1;
break;
}
}
// 当前i为周期起点,后缀和<res,就需要查找前i中是否有一个X满足
else{
int l=0,r=i;
while(l+1<r){
int mid=(l+r)>>1;
if(check1(mid,i)) r=mid;
else l=mid;
}
if(b[r]+b[n]-b[i-1]==res)
{
flag=1;
break;
}
}
}
if(flag==1) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
标签:AtCoder,12,return,Contest,int,res,mid,else,flag
From: https://blog.csdn.net/qq_73819342/article/details/144634699