训练情况
赛后反思
C题逆风翻盘,可能勉强青名了。A题愣神了,我觉得还能再做的快一点。
A题
给定一个字符串,NWSE,重复着字符串走,我们直接模拟即可,用 while 来判断是否走到终点,然后对于不可能走到的终点,我选择了一个不会超时的步数范围,超出就跳出 while 即可,最后判断人有没有在 \((a,b)\) 即可。
#include <bits/stdc++.h>
#define int long longusing namespace std;void solve(){int n,a,b; string s;cin>>n>>a>>b;cin>>s;int tot = 0;int x = 0,y = 0;while(tot <= 100000 && !(x == a && y == b)){if(s[tot%n] == 'N') y++;else if(s[tot%n] == 'S') y--;else if(s[tot%n] == 'W') x--;else if(s[tot%n] == 'E') x++;// cout<<x<<" "<<y<<endl;tot++;}if(x == a && y == b) cout<<"YES"<<endl;else cout<<"NO"<<endl;
}signed main(){int T; cin>>T; while(T--)solve();return 0;
}
C题
这题其实挺难看出一个二分单调性的,我们选择二分给自己的美味值,如果这个值过大会让剩下的不够分,过小会让剩下的太多,对于自己的美味值,由于切出来是连续的,我们可以通过双指针来找到自己左右边界,再维护一个前后缀 \(> v\) 的个数,判断左右边界的个数和是否能 \(\ge m\) 即可。
#include <bits/stdc++.h>
#define int long longusing namespace std;const int N = 2e5 + 3;int n,m,v;
int sum;
vector<int> a(N);
vector<int> pre(N);
vector<int> suf(N);bool pd(int x){int l = 1,r = 1,now = 0;for(r = 1;r<=n;r++){now += a[r];while(now - a[l] >= x && l <= r) now-=a[l],l++;if(now >= x){if(pre[l-1] + suf[r+1] >= m){// cout<<x<<" "<<l<<" "<<r<<endl;return true;}}}return false;
}void solve(){cin>>n>>m>>v;sum = 0;for(int i = 1;i<=n;i++) cin>>a[i],sum+=a[i];for(int i = 1;i<=n;i++) pre[i] = 0,suf[i] = 0;int now = 0;for(int i = 1;i<=n;i++){now+=a[i];if(now >= v) now = 0,pre[i]++;}now = 0;for(int i = n;i;i--){now+=a[i];if(now >= v) now = 0,suf[i]++;}for(int i = 1;i<=n;i++) pre[i] += pre[i-1];for(int i = n;i;i--) suf[i] += suf[i+1];// for(int i = 1;i<=n;i++) cout<<pre[i]<<" "; cout<<endl;// for(int i = 1;i<=n;i++) cout<<suf[i]<<" "; cout<<endl;int l = 0,r = sum,m;while(l<r){m = l + r + 1 >> 1;if(pd(m)) l = m;else r = m - 1;}if(pd(r)) cout<<r<<endl;else cout<<-1<<endl;
}signed main(){int T; cin>>T; while(T--)solve();return 0;
}