CF變紅之路_Educational Codeforces Round 53 (Rated for Div. 2)
阿新 • • 發佈:2019-01-30
昨天打的一場比賽,開始AB題出的很順,C題不會做(沒想到二分的思路),D題出的較慢,一共出了3道題排名1003。今天又重新做了C題發現思路雖然很巧妙,但也是正常的二分思路。
A
簽到題,看懂題就會寫。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 100;
char s[maxn];
int main() {
int n;
cin >> n;
scanf("%s", s);
int flag = 1;
for(int i = 1; i < n; i++) {
if(s[i] != s[i-1]) {
cout << "YES" << endl;
cout << s[i-1] << s[i] << endl;
flag = 0;
break;
}
}
if(flag) cout << "NO" << endl;
return 0;
}
B
用set維護已經拿出的書,在set裡的一律輸出0然後再找下一個不在set的,遍歷的過程中放到set中。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 100;
int a[maxn];
int b[maxn];
int main() {
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
}
set< int> st;
int cur = 1;
for(int i = 1; i <= n; i++)
{
int tmp = b[i];
if(st.count(tmp)) {
printf("0 ");
continue;
}
int ret = 1;
while(a[cur] != tmp) {
st.insert(a[cur]);
cur++;
ret++;
}
cur++;
printf("%d ", ret);
}
return 0;
}
C
題目大意:給出一個字串,其中每個字元代表移動的方向,起點是原點,然後給出一個座標,問如果無需修改其中的操作就能到達座標的話輸出0如果在不增減的條件下修改不能到的話輸出-1,否則輸出修改最小的區間的大小。
思路:輸出的0和-1兩種情況直接特判就行,然後二分猜最小區間的大小然後放判斷,判斷的方法也很巧妙,區間和的思路可以極大的減少重複計算量。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = (int)2e5 + 100;
char s[maxn];
ll sx[maxn], sy[maxn];
ll getSum(ll l, ll r, ll* a) { // 求區間和
return a[r] - a[l - 1];
}
bool ok(ll x, ll y, ll n) { // 判斷操作n次能否位移量為(x,y)
x = abs(x);
y = abs(y);
return x + y <= n && ((x + y) & 1) == (n & 1);
}
bool judge(ll m, ll n, ll x, ll y) {
bool flag = false;
for (ll i = 1; i + m - 1 <= n; i++) {
ll xx = sx[n] - getSum(i, i + m - 1, sx);
ll yy = sy[n] - getSum(i, i + m - 1, sy);
flag |= ok(x - xx, y - yy, m);
if (flag) return true;
}
return false;
}
int main() {
ll n, x, y;
scanf("%lld%s%lld%lld", &n, s + 1, &x, &y);
sx[0] = sy[0] = 0;
for (int i = 1; i <= n; i++) {
sx[i] = sx[i - 1];
sy[i] = sy[i - 1];
sx[i] += (s[i] == 'R');
sx[i] -= (s[i] == 'L');
sy[i] += (s[i] == 'U');
sy[i] -= (s[i] == 'D');
}
if (sx[n] == x && sy[n] == y) {
cout << 0 << endl;
return 0;
}
if (!ok(x, y, n)) {
cout << -1 << endl;
return 0;
}
ll l = 0, r = n;
while (r - l > 1) {
ll m = (l + r) >> 1;
if (judge(m, n, x, y)) {
r = m;
} else {
l = m;
}
}
cout << r << endl;
return 0;
}
D
由於T很大,直接for迴圈模擬的話必定超時,可以先求和然後判斷能走幾圈(在不跳的情況下),如果不能不跳,即和大於擁有的金額,那麼遍歷一次,和減去不能支付的,在判斷能走幾圈,迴圈的終止條件是所有的都不能支付。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 100;
ll v[maxn];
bool vis[maxn];
bool cmp(ll a, ll b) {
return a > b;
}
int main() {
ll n,have;
cin >> n >> have;
ll sum = 0;
for(ll i = 0; i < n; i++) {
scanf("%lld", &v[i]);
sum += v[i];
}
ll cnt = n;
ll ans = 0;
memset(vis, false, sizeof vis);
while(cnt) {
if(sum <= have) {
ans += (have / sum)*cnt;
have -= (have / sum) * sum;
}
for(int i = 0; i < n; i++) {
if(vis[i]) continue;
if(v[i] > have) {
cnt--;
vis[i] = true;
sum-=v[i];
continue;
}
else {
have -= v[i];
ans++;
}
}
}
cout << ans << endl;
return 0;
}