codeforces round #424 div2
A 暴力查询,分三段查就可以了
#include<bits/stdc++.h> using namespace std; const int N = 110; int n, pos; int a[N]; int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); pos = -1; for(int i = 2; i <= n; ++i) if(a[i] - a[i - 1] <= 0) { pos = i; break; } if(pos == -1) { puts("YES"); return 0; } for(int i = pos; i <= n; ++i) { pos = 0; if(a[i] - a[i - 1] > 0) { puts("NO"); return 0; } else if(a[i] - a[i - 1] < 0) { pos = i; break; } } if(!pos) { puts("YES"); return 0; } for(int i = pos; i <= n; ++i) { if(a[i] - a[i - 1] >= 0) { puts("NO"); return 0; } } puts("YES"); return 0; }
B 开个数组映射一下
#include<bits/stdc++.h> using namespace std; const int N = 1010; int n; char s1[N], s2[N], s[N]; int Map[N]; int main() { scanf("%s%s%s", s1 + 1, s2 + 1, s + 1); n = strlen(s1 + 1); for(int i = 1; i <= n; ++i) Map[s1[i] - 'a'] = s2[i] - 'a'; for(int i = 1; i <= strlen(s + 1); ++i) { if(isdigit(s[i])) printf("%c", s[i]); if(islower(s[i])) printf("%c", (char)(Map[s[i] - 'a'] + 'a')); if(isupper(s[i])) printf("%c", (char)(Map[s[i] - 'A'] + 'A')); } return 0; }
C 没想出来,这种题目发现用b在a上算不行就应该转换用a在b上算。统计每个b对于每个a产生的初始值,如果一个初始值出现了k次,那么就是可以的。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2010; ll tot; int n, k, ans; ll a[N]; map<ll, int> mp; vector<ll> v; inline int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; ++i) { a[i] = read() + a[i - 1]; v.push_back(a[i]); } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); for(register int i = 1; i <= k; ++i) { int x; x = read(); for(int j = 0; j < v.size(); ++j) ++mp[x - v[j]]; } for(map<ll, int> :: iterator it = mp.begin(); it != mp.end(); ++it) ans += (it -> second == k); printf("%d\n", ans); return 0; }
D dp,dp[i][j]表示第i个人选到第j个钥匙,dp[i][j]=min(dp[i][j-1],max(dp[i-1][j-1],abs(a[i]-b[j])+(b[j]-p))就好了
看错题目+C题 这道题1小时35分才出来。。。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2010; int n, k, p; int a[N], b[N]; ll dp[N][N]; int main() { scanf("%d%d%d", &n, &k, &p); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= k; ++i) scanf("%d", &b[i]); sort(a + 1, a + n + 1); sort(b + 1, b + k + 1); for(int i = 1; i <= n; ++i) dp[i][0]= 1e16; for(int i = 1; i <= n; ++i) for(int j = 1; j <= k; ++j) dp[i][j] = min(dp[i][j - 1], max(dp[i - 1][j - 1], (ll)abs(a[i] - b[j]) + (ll)abs(b[j] - p))); ll ans = 1e16; for(int i = n; i <= k; ++i) ans = min(ans, dp[n][i]); printf("%lld\n", ans); return 0; }
E 平衡树练习题 其实很简单就能搞定。我们发现如果选了一轮序列就会恢复原来的样子,只是删除了一些数。那么我们开set记录每个数出现的位置,从最小的数开始枚举,如果没到结尾加上上次到这次的距离,否则回到开头,因为每个数只删除一次,我们用size记录需要加上的答案,每删除一次size减1,到了一轮结束加上size。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 100010; int n, sz; ll ans; int a[N], tree[N]; set<int> s[N]; int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); s[a[i]].insert(i); } sort(a + 1, a + n + 1); int last = 0; ans = n; sz = n; for(int i = 1; i <= n; ++i) { set<int> :: iterator it = s[a[i]].lower_bound(last); if(it == s[a[i]].end()) { ans += sz; it = s[a[i]].begin(); } last = *it; --sz; s[a[i]].erase(it); } printf("%lld\n", ans); return 0; }