专栏文章
abc388f
AT_abc388_f题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqjeate
- 此快照首次捕获于
- 2025/12/04 05:46 3 个月前
- 此快照最后确认于
- 2025/12/04 05:46 3 个月前
有一个 的做法,设 表示 是否可以到达。
然而,注意到只需要关注每一段区间前的 个和后 个位置的 状态,其他的都可以用同余最短路找到规律(当然,由于 很小,也可以直接暴力)。所以复杂度降为 。
code:
CPPconst int MAXN=2e4+5;
bool can[MAXN];
ll n,m,a,b,lcm,gcd;
int l[MAXN],r[MAXN];
vector<int>pos;
bool cou(int l,int r){
if(r<=0||l<=0)return false;
if(l>r)return false;
if(r>n)return false;
int len=r-l;
if(len%gcd!=0){
return false;
}
if(len>lcm)return true;
return can[len];
}
bool check(int x){
for(int i=0;i<pos.size();i++){
if(cou(pos[i],x)){
return true;
}
}return false;
}
bool check_(int x){
for(int i=0;i<pos.size();i++){
if(x-pos[i]>=a&&x-pos[i]<=b){
return true;
}
if(pos[i]==x){
return true;
}
}return false;
}
map<int,bool>mp;
signed main(){
scanf("%lld%lld%lld%lld",&n,&m,&a,&b);
for(int i=1;i<=m;i++){
scanf("%lld%lld",&l[i],&r[i]);
if(l[i]+b<=r[i]){
printf("No\n");
return 0;
}
for(int j=l[i];j<=r[i];j++){
mp[j]=true;
}
}
lcm=a*b/__gcd(a,b);
gcd=__gcd(a,b);
can[0]=true;
for(int i=1;i<=lcm;i++){
if(i>=a)can[i]|=can[i-a];
if(i>=b)can[i]|=can[i-b];
}pos.push_back(1);
l[m+1]=n+1;
for(int i=1;i<=m;i++){
vector<int>t;
for(int j=0;j<=b;j++){
if(!mp[l[i]-j]&&check(l[i]-j)){
t.push_back(l[i]-j);
}
}
for(int j=0;j<pos.size();j++){
if(pos[j]>r[i]){
t.push_back(pos[j]);
}
}
pos.clear();
for(int j=0;j<t.size();j++)pos.push_back(t[j]);
t.clear();
for(int j=0;j<=b;j++){
if(!mp[r[i]+j]&&check_(r[i]+j)){
pos.push_back(r[i]+j);
t.push_back(r[i]+j);
}
}
pos.swap(t);
}
if(check(n)){
printf("Yes");
}else{
printf("No");
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...