- 水几个题,熟悉一下键盘。。。
- 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;
}