概述
题目链接
F.Almost Sorted Array(HDU5532)
分析
不妨先解决这个问题的判断非降序的部分。既然符合条件的数组移除一个数字就能使得整个数组非降序,那么我们先统计满足
a[i−1]>a[i]
的i的个数cnt。另外,令idx等于当
cnt=1
时的满足
a[i−1]>a[i]
i的值。
下面根据cnt的值来分类讨论:
- 当 cnt=0 时数组满足条件。
- 当 cnt>1 时数组不满足条件。
- 当 cnt=1 时, idx=1 或 idx=n−1 的话满足条件(删去数组的某端就能满足条件),删去a[idx-1]或a[idx]能够使得整个数组非降序的话也满足条件,否则就不满足条件。
对非升序的判断只要把数组颠倒一下顺序,然后重复非降序的判断方法即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int t, n, a[maxn];
bool isIncrease() {
int idx, cnt = 0;
for(int i = 1; i < n; i++) {
if(a[i-1] > a[i]) {
idx = i;
cnt++;
}
}
if(cnt == 0) return true;
if(cnt > 1) return false;
if(idx == 1 || idx == n - 1) {
return true;
}
if(a[idx-1] <= a[idx+1]) {
return true;
}
if(a[idx-2] <= a[idx]) {
return true;
}
return false;
}
bool isDecrease() {
reverse(a, a + n);
return isIncrease();
}
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
if(isIncrease() || isDecrease()) {
puts("YES");
}
else puts("NO");
}
return 0;
}
G.Dancing Stars on Me(HDU5533)
分析:
本题需要判断若干个点是否正好构成一个正多边形。刚开始想得很复杂,觉得应该先求个凸包来判断是否这些点收是否正好构成一个凸多边形。后来才发现,这些点构成正多边形只须满足它们的重心到各个点的距离相等就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
struct Point {
double x, y;
Point(double x = 0, double y = 0): x(x), y(y) {}
double distance(Point p) {
return hypot(x - p.x, y - p.y);
}
};
const double eps = 1e-10;
const int maxn = 105;
int t, n;
double x, y, sx, sy;
Point p[maxn];
int dcmp(double x) {
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
int main() {
scanf("%d", &t);
for(; t--;) {
scanf("%d", &n);
sx = sy = 0;
for(int i = 0; i < n; i++) {
scanf("%lf%lf", &x, &y);
p[i] = Point(x, y);
sx += x;
sy += y;
}
bool flag = true;
Point c = Point(sx / n, sy / n);
double dis = c.distance(p[0]);
for(int i = 1; i < n; i++) {
if(dcmp(c.distance(p[i]) - dis)) {
flag = false;
break;
}
}
puts(flag ? "YES" : "NO");
}
return 0;
}
H.Partial Tree(HDU5537)
分析
由于满足连通性和
n=m−1
(其中为
n
点数,
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int t, n, m, f[maxn], d[maxn];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
m = n - 2;
for(int i = 1; i < n; i++) {
scanf("%d", &f[i]);
}
memset(d, 0, sizeof(d));
d[0] = n * f[1];
for(int i = 2; i < n; i++) {
for(int j = i - 1; j <= m; j++) {
d[j] = max(d[j], d[j-(i-1)] + f[i] - f[1]);
}
}
printf("%dn", d[m]);
}
return 0;
}
J.Chip Factory(HDU5536)
分析
求集合中两个数的最大异或值,这样的问题非常适合用 Trie来高效的求解。先将所有的数的二进制表示的字符串插入Trie。然后枚举两个数i, j,并将这两个数删除,接着直接在Trie中找与i + j的异或值最大的那个数,并更新最大值。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10, maxNode = 1e7;
int t, n, a[maxn], ans;
struct trie {
int sz, val[maxNode], ch[maxNode][2];
void init() {
memset(ch[0], 0, sizeof(ch[0]));
sz = 1;
}
void update(int num, int v) {
int u = 0;
for(int i = 30; i >= 0; i--) {
int c = (num >> i) & 1;
if(ch[u][c] == 0) {
memset(ch[sz], 0, sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
val[u] += v;
}
}
int match(int num) {
int u = 0, ans = 0;
for(int i = 30; i >= 0; i--) {
int c = (num >> i) & 1;
if(ch[u][c^1] && val[ch[u][c^1]]) {
ans |= (1 << i);
u = ch[u][c^1];
}
else u = ch[u][c];
}
return ans;
}
}o;
int main() {
scanf("%d", &t);
for(; t--;) {
scanf("%d", &n);
o.init();
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
o.update(a[i], 1);
}
ans = 0;
for(int i = 0; i < n; i++) {
o.update(a[i], -1);
for(int j = i + 1; j < n; j++) {
o.update(a[j], -1);
int tmp = o.match(a[i] + a[j]);
ans = max(ans, tmp);
o.update(a[j], 1);
}
o.update(a[i], 1);
}
printf("%dn", ans);
}
return 0;
}
L.House Building(HDU5538)
分析
我们可以枚举柱体(即矩阵中的元素)。对每个柱体,计算它的高度与四个方向上的柱体的高度差d,另外考虑柱顶也要贴玻璃,所以计算出该柱体对答案的贡献为d + 1。注意,由于每组的输入的矩阵规模可能不同,所以进入每组的计算前都要对二维数组进行初始化(或者显式地对边界情况进行判断)。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 55;
// 用于表示四个方向坐标变化情况的二维数组
const int dir[2][4] = {{-1, 1, 0, 0}, {0, 0, -1, 1}};
int t, x, y, n, m, d, sum, c[maxn][maxn];
int main() {
scanf("%d", &t);
for(; t--;) {
sum = 0;
scanf("%d%d", &n, &m);
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%d", &c[i][j]);
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(c[i][j]) sum++;
else continue;
// 枚举四个方向
for(int k = 0; k < 4; k++) {
x = i + dir[0][k];
y = j + dir[1][k];
d = c[i][j] - c[x][y];
// 正的落差才能被加到结果中
if(d > 0) sum += d;
}
}
}
printf("%dn", sum);
}
return 0;
}
(其他题目略)
最后
以上就是合适小蚂蚁为你收集整理的【解题报告】2015ACM/ICPC亚洲区长春站的全部内容,希望文章能够帮你解决【解题报告】2015ACM/ICPC亚洲区长春站所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复