A. Mike and Cellphone(Codeforces 689A)
思路
当输入号码的相对位置形成的图形无法平移是就输出”YES”,否则输出”NO”。将平移分类成向上平移,向下平移,向左平移和向右平移三种情况。若输入数据包含1,2或3都使得图形不能上移,若输入数据包含7, 9或0都使得图形不能向下平移,若输入数据包含1, 4, 7或0都使得图形不能向左平移,若输入数据包含3, 6, 9或0都使得图形不能向右平移。因此总而言之,这四种平移都不能进行的时候就输出”YES”,否则输出”NO”。
代码
#include <bits/stdc++.h>
using namespace std;
bool U = true, D = true, L = true, R = true, vis[20];
char ch;
int n, num;
int main() {
scanf("%d\n", &n);
for(int i = 0; i < n; i++) {
scanf("%c", &ch);
num = ch - '0';
vis[num] = true;
}
if(vis[7] == true || vis[9] == true || vis[0] == true) {
D = false;
}
if(vis[1] == true || vis[2] == true || vis[3] == true) {
U = false;
}
if(vis[1] == true || vis[4] == true || vis[7] == true || vis[0]) {
L = false;
}
if(vis[3] == true || vis[6] == true || vis[9] == true || vis[0]) {
R = false;
}
puts((D == false && U == false && L == false && R == false) ? "YES" : "NO");
return 0;
}
B. Mike and Shortcuts(Codeforces 689B)
思路
原本想的是用动态规划来做,后来发现由于捷径的存在,最优路径可能是一个先前进,然后后退,再前进反复进行的路径。例如,从
1
至
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair <int, int> p;
const int maxn = 2e5 + 10, INF = maxn;
int n, v;
struct edge {
int to, dist;
edge() {}
edge(int to, int dist): to(to), dist(dist) {}
};
struct Dijkstra {
int d[maxn];
vector <edge> G[maxn];
void addEdge(int u, int v, int w) {
G[u].push_back(edge(v, w));
}
void solve(int s) {
fill(d + 1, d + n + 1, INF);
d[s] = 0;
priority_queue < p, vector<p>, greater<p> > pq;
pq.push(p(0, s));
while(!pq.empty()) {
p node = pq.top();
pq.pop();
int u = node.second;
if(node.first > d[u]) {
continue;
}
for(int i = 0; i < G[u].size(); i++) {
edge& e = G[u][i];
int v = e.to;
int w = e.dist;
if(d[v] > d[u] + w) {
d[v] = d[u] + w;
pq.push(p(d[v], v));
}
}
}
}
}o;
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &v);
o.addEdge(i, i + 1, 1);
o.addEdge(i + 1, i, 1);
o.addEdge(i, v, 1);
}
o.solve(1);
for(int i = 1; i <= n; i++) {
printf("%d ", o.d[i]);
}
puts("");
return 0;
}
C. Mike and Chocolate Thieves(Codeforces 689C)
思路
从
m
得知
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m, l, r, mid;
ll c(ll n) {
ll res = 0;
for(ll q = 2; n >= q * q * q; q++) {
res += n / (q * q * q);
}
return res;
}
int main() {
cin >> m;
l = 7;
r = 100 * m;
while(r - l > 1) {
mid = (l + r) >> 1;
if(c(mid) >= m) {
r = mid;
}
else {
l = mid;
}
}
if(c(r) == m) {
cout << r << endl;
}
else {
cout << -1 << endl;
}
return 0;
}
D. Friends and Subsequences(Codeforces 689D)
思路
我们定义
max(i,j)
为
a[i]
到
a[j]
之间的最大值。那么
max
函数有这样的性质:当
i
为定值的时候,
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int n, lb, ub, a[maxn], b[maxn];
ll ans;
struct table {
int stTable[maxn][32][2];
int preLog2[maxn];
void init(int n, int* array) {
preLog2[1] = 0;
for(int i = 2; i <= n; i++) {
preLog2[i] = preLog2[i-1];
if((1 << preLog2[i] + 1) == i) {
++preLog2[i];
}
}
for(int i = n - 1; i >= 0; i--) {
stTable[i][0][0] = stTable[i][0][1] = array[i];
for(int j = 1; (i + (1 << j) - 1) < n; j++) {
stTable[i][j][0] = max(stTable[i][j-1][0], stTable[i+(1<<j-1)][j-1][0]);
stTable[i][j][1] = min(stTable[i][j-1][1], stTable[i+(1<<j-1)][j-1][1]);
}
}
}
int rmq(int l, int r, int d) {
int len = r - l + 1, k = preLog2[len];
if(d == 0) {
return max(stTable[l][k][0], stTable[r-(1<<k)+1][k][0]);
}
else {
return min(stTable[l][k][1], stTable[r-(1<<k)+1][k][1]);
}
}
}A, B;
int binary(int L, int& lb, int& ub) {
int l = L - 1, r = n;
while(r - l > 1) {
int mid = (l + r) >> 1;
int tmp = A.rmq(L, mid, 0) - B.rmq(L, mid, 1);
if(tmp < 0) {
l = mid;
}
else {
r = mid;
}
}
lb = r;
l = L - 1, r = n;
while(r - l > 1) {
int mid = (l + r) >> 1;
int tmp = A.rmq(L, mid, 0) - B.rmq(L, mid, 1);
if(tmp <= 0) {
l = mid;
}
else {
r = mid;
}
}
ub = r;
}
int main() {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
A.init(n, a);
for(int i = 0; i < n; i++) {
scanf("%d", &b[i]);
}
B.init(n, b);
for(int L = 0; L < n; L++) {
binary(L, lb, ub);
ans += ub - lb;
}
printf("%I64d\n", ans);
return 0;
}
(其它题目略)