- 水几个题,熟悉一下键盘。。。
- HDU5532 Almost Sorted Array
- 题意: ASA 定义为,仅去掉一个( One and Only One )元素后数组是非降序或者非升序。
- 题解:很明显,判断一个序列是否有序可以通过判断其 Longest NonDecreasing Subsquence 或者 Longest NonIncreasing Subsquence 是否等于序列长度来得到。
/* **********************************************
File Name: test.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015/11/1 12:34:01
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0xfffffff;
const int MAX = 100007;
int a[MAX];
int dp[MAX]; //dp[i] length is i min
int inc(int n) {
fill(dp, dp + n + 1, INF);
dp[0] = -INF;
for (int i = 1; i <= n; ++i) {
int sz = upper_bound(dp, dp + i, a[i]) - dp;
//printf("get %d\n", sz);
dp[sz] = a[i];
}
for (int i = n; i >= 1; --i) {
if (dp[i] < INF) {
return i;
}
}
return 0;
}
int dec(int n) {
reverse(a + 1, a + n + 1);
return inc(n);
}
int main() {
int T, n;
scanf(" %d", &T);
while (T--) {
scanf(" %d", &n);
for (int i = 1; i <= n; ++i) {
scanf(" %d", a + i);
}
puts((inc(n) >= n - 1 || dec(n) >= n - 1) ? "YES" : "NO");
}
return 0;
}
- HDU5233 Dancing Stars on Me
- 题意:求一堆点是否构成一个正 n 边形
- 题解:求凸包,判断一下
→
- 凸包顶点个数是否为 n
- 凸包所有边是否等长
/* **********************************************
File Name: 5533.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015年11月02日 星期一 20时33分46秒
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const double INF = FLT_MAX;
const double EPS = 1e-8;
const double PI = acos(-1.0);
const int MAX = 107;
inline int sign(double x) {
if (fabs(x) < EPS) return 0;
if (x > 0.0) return 1;
return -1;
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y): x(_x), y(_y) {}
Point operator-(const Point& ne)const {
return Point(x - ne.x, y - ne.y);
}
Point operator+(const Point& b)const {
return Point(x + b.x, y + b.y);
}
Point operator*(const double t)const {
return Point(t * x, t * y);
}
Point operator/(const double t)const {
if (sign(t) == 0) return Point(INF, INF);
return Point(x / t, y / t);
}
double operator^(const Point& b)const {
return (x - b.x) * (x - b.x) + (y - b.y) * (y - b.y);
}
} ping[MAX];
struct Polygon {
Point p[MAX];
int n;
} ans;
inline double xmult(Point o, Point a, Point b) {
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
bool cmp(const Point& a, const Point& b) {
return a.x < b.x || (sign(a.x - b.x) == 0 && a.y < b.y);
}
void convex_hull(Point p[MAX], int n, Polygon& res) {
res.n = 0;
sort(p, p + n, cmp);
int i, j, top;
for (i = 0, top = 0; i < n; ++i) {
while (top > 1 && xmult(res.p[top - 2], res.p[top - 1], p[i]) < EPS) {
--top;
}
res.p[top++] = p[i];
}
j = top;
for (i = n - 2; i >= 0; --i) {
while (top > j && xmult(res.p[top - 2], res.p[top - 1], p[i]) < EPS) {
--top;
}
res.p[top++] = p[i];
}
res.n = top - 1;
}
int main() {
int T, n;
scanf(" %d", &T);
while (T--) {
scanf(" %d", &n);
for (int i = 0; i < n; ++i) {
scanf(" %lf %lf", &ping[i].x, &ping[i].y);
}
convex_hull(ping, n, ans);
if (n < 3 || ans.n != n) {
puts("NO");
continue;
}
double leng = ans.p[0] ^ ans.p[n - 1];
bool flag = true;
for (int i = 0; i < n - 1; ++i) {
if (sign((ans.p[i] ^ ans.p[i + 1]) - leng)) {
flag = false;
break;
}
}
puts(flag ? "YES" : "NO");
}
return 0;
}
HDU5534 Partial Tree - 题意:
n
个点连成一棵树,对某个顶点
v ,若其度为 degv ,则价值为 fdegv 题解: n 个点,
n−1 条边,共有 2∗n−2 个度需要分配。可以证明,首先对每个顶点赋一个度,将剩余的 n−2 个度任意分配给剩下的顶点,均可以得到一棵树。我们可以简单地反证一下~- 对每个顶点,最少可能分配到
1
个度,最多可能分配到个度,这是满足任意一个顶点的度的限制条件 1≤degv≤n−1 的。
1+(n−2)=n−1 -
2∗n−2
个度分配完后,我们可以开始两两顶点连边,每连一条边,二者的度分别减
1
,先不考虑是否会造成环,那么
- ① 当仅剩
2 个度时,将对应的两个点连一条边,即完成连边 - ② 当多余
2
个度时,假设剩余
k 个度,只需要任意选择两个度还没用完的点连接起来,就可以达到度剩余 k−2 的局面
- ① 当仅剩
- 由①②可知, 恰好可以连出
2∗n−22=n−1条边。此时,根据我们开始的分配,没有任何一个点是没有连至少一条边的,于是不可能存在孤立顶点;另外,,,,窝好像不能证明整个图的连通性鸭(;′⌒`)。。。
- 于是可以换一个方向考虑,窝们考虑一个放射形图案,一个点度为
n−1
,作为根,其他所有点都是它的孩子,此时为
1+1+⋯+(n−1)
的组合,将一个点拿下,连到其它点上,变成
1+1+⋯+2+(n−2)
的组合,相当于最后的
n−2
个度分了
1
个出去,如此下去,可以达到将
n−2 分解的任何一种组合。
- 对每个顶点,最少可能分配到
1
个度,最多可能分配到
题解续:做完上述分析,我们就可以先考虑一个简化版本了。容量为 n−2 的背包,有 n−1 件物品,分别为大小为 i ,价值为
fi ,有无限多个,问装满背包最大获得价值为多少。
/* **********************************************
File Name: 5534.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015/11/3 22:22:19
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int INF = 0xfffffff;
const int MAX = 2018;
vector<P> bag;
int dp[MAX];
int f[MAX];
int m;
void push(int weight, int value) {
for (int i = 1; i * weight <= m; i <<= 1) {
bag.push_back(P(weight * i, value * i));
//printf("push (%d, %d)\n", weight * i, value * i);
}
}
int main() {
int T, n;
scanf(" %d", &T);
while (T--) {
bag.clear();
scanf(" %d", &n);
m = n - 2;
for (int i = 1; i < n; ++i) {
scanf(" %d", f + i);
}
int ans = n * f[1];
for (int i = 2; i < n; ++i) {
push(i - 1, f[i] - f[1]);
}
sort(bag.begin(), bag.end());
unique(bag.begin(), bag.end());
fill(dp, dp + m + 1, -INF);
dp[0] = 0;
for (int i = 0; i < bag.size(); ++i) {
for (int j = m; j >= bag[i].first; --j) {
if (dp[j - bag[i].first] + bag[i].second > dp[j]) {
dp[j] = dp[j - bag[i].first] + bag[i].second;
}
}
}
printf("%d\n", dp[m] + ans);
}
return 0;
}
- HDU5536 Chip Factory
- 题意:问最大的
(si+sj)⊕sk
- 题解:将所有数归一化为 32 bit 的串,建立 Trie 树求解即可。复杂度 log(n2)∗n
/* **********************************************
File Name: 5536.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015/11/3 21:38:44
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAX = 1LL << 32;
const int CNT = 1024;
int a[CNT];
struct Node {
Node* son[2];
int cnt;
Node(int _x = 0): cnt(_x) {
son[0] = son[1] = NULL;
}
};
void insert(Node* T, int x) {
for (ll ck = MAX; ck > 0; ck >>= 1) {
int idx = (x & ck) > 0 ? 1 : 0;
if (T->son[idx] == NULL) {
T->son[idx] = new Node();
}
++(T->son[idx]->cnt);
T = T->son[idx];
}
}
void remove(Node* T, int x) {
for (ll ck = MAX; ck > 0; ck >>= 1) {
int idx = (x & ck) > 0 ? 1 : 0;
--(T->son[idx]->cnt);
T = T->son[idx];
}
}
void clear(Node* T) {
if (T == NULL) {
return;
}
for (int i = 0; i < 2; ++i) {
clear(T->son[i]);
}
delete T;
}
int gao(Node* T, int x) {
int res = 0;
for (ll ck = MAX; ck > 0; ck >>= 1) {
int idx = (x & ck) > 0 ? 1 : 0;
res <<= 1;
if (T->son[idx ^ 1] != NULL && T->son[idx ^ 1]->cnt > 0) {
T = T->son[idx ^ 1];
res |= idx ^ 1;
} else {
T = T->son[idx];
res |= idx;
}
}
return res;
}
int main() {
int T, n;
scanf(" %d", &T);
while (T--) {
scanf(" %d", &n);
Node* T = new Node();
for (int i = 0; i < n; ++i) {
scanf(" %d", a + i);
insert(T, a[i]);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
remove(T, a[i]);
for (int j = 0; j < n; ++j) {
if (j == i) continue;
remove(T, a[j]);
int res = gao(T, a[i] + a[j]);
//printf("remove %d, %d, get %d\n", a[i], a[j], res);
ans = max(ans, res ^ (a[i] + a[j]));
//ans = max(ans, gao(T, a[i] + a[j]));
insert(T, a[j]);
}
insert(T, a[i]);
}
clear(T);
printf("%d\n", ans);
}
return 0;
}
- HDU5538 House Building
- 题意:一坨物体放在地上,求表面积,当然,是放在地上,底面就不算。。。
- 题解:考虑每个方块的顶面,以及四个侧面即可(如对右侧面,计入的面积应为 max(0,ai,j+1−ai,j) ),其中顶面面积恒为1。注意考虑该方块不存在时的情况,此时顶面面积为0。
/* **********************************************
File Name: 5538.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015年11月02日 星期一 20时31分00秒
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAX = 64;
int a[MAX][MAX];
int main() {
int T, n, m;
scanf(" %d", &T);
while (T--) {
scanf(" %d %d", &n, &m);
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf(" %d", &a[i][j]);
}
}
int sum = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (a[i][j] > 0) ++sum;
sum += max(0, a[i][j] - a[i - 1][j]);
sum += max(0, a[i][j] - a[i][j - 1]);
sum += max(0, a[i][j] - a[i + 1][j]);
sum += max(0, a[i][j] - a[i][j + 1]);
}
}
printf("%d\n", sum);
}
return 0;
}