传送门:http://acm.hdu.edu.cn/search.php?field=problem&key=BestCoder+Round+%2391&source=1&searchmode=source
A题:给你n种字母,每种字母有个权值vali,共cnti个,现在让你在里面挑出任意数量的字符,组合成一个字符串,该字符串的权值的计算方式为val1*1+val2*2+……+valn*n,让你输出字符串最大的权值是多少。这题很容易会有一个错误的贪心,就是把val为负的舍去,然后val从小到大选择。事实上负值时可以选的,比如字符1的权值为-1,字符2的权值为2,字符3的权值为3,那么如果我不选字符1,总权值为2*1+3*2=8,小于选了字符1的权值-1*1+2*2+3*3=12,所以这种贪心是错的。正解是先按val对字符排序,很明显,val大的字符如果不选,val小的就一定不会选。也即是,如果字符ch选了,权值比它大的肯定也会选。那假设它选了,总权值就会增加valch+valch+1,valch+2……valn,因此只要判断valch+valch+1,valch+2……valn是不是大于0,就能确定ch到底要不要选了。可以预处理下后缀和,然后直接扫一遍。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; pii N[100]; vector <int> V; int sum[maxn]; int main() { int T; scanf("%d", &T); while (T--) { V.clear(); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d%d", &N[i].X, &N[i].Y); while (N[i].Y--) V.pb(N[i].X); } sort(V.begin(), V.end()); sum[V.size()] = 0; for (int i = V.size() - 1; i >= 0; i--) sum[i] = sum[i+1] + V[i]; ll ans = 0, k = 1; for (int i = 0; i < V.size(); i++) if (V[i] >= 0 || V[i] + sum[i+1] >= 0) { ans += k * V[i]; k++; } printf("%I64d\n", ans); } return 0; }
B题:有n种植物,每种植物有个适宜温度区间,如果温度适宜,它可以提供ai的研究价值,如果温度大于适宜温度的上限,它可以提供bi的研究价值,如果温度小于适宜温度的下限,它可以提供ci的研究价值。现在让你找到一个温度,使得总研究价值最大,温度可以为任意实数。输出最大总研究价值。先离散化一下温度,然后线段树维护下最大研究价值。注意由于温度是实数,所以离散的时候要,两个数之间要多加一个空位,用于浮点数的统计。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 using namespace std; typedef long long LL; typedef pair<int, int> pii; const int maxn = 2e5 + 10; const int inf = 0x3f3f3f3f; struct node1 { int l, r, a, b, c; } N[maxn]; vector<pii> V; LL add[maxn<<2]; LL Max[maxn<<2]; void PushUp(int rt) { Max[rt] = max(Max[rt<<1] , Max[rt<<1|1]); } void PushDown(int rt, int m) { if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; Max[rt<<1] += add[rt]; Max[rt<<1|1] += add[rt]; add[rt] = 0; } } void update(int L, int R, int c, int l, int r, int rt) { if (L <= l && r <= R) { add[rt] += c; Max[rt] += c; return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (m < R) update(L , R , c , rson); PushUp(rt); } LL query(int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return Max[rt]; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret = max(ret, query(L , R , lson)); if (m < R) ret = max(ret, query(L , R , rson)); return ret; } void init() { V.clear(); clr(add, 0); clr(Max, 0); } int main() { int T; scanf("%d", &T); while (T--) { init(); V.pb(make_pair(0,-1)); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d%d%d%d%d", &N[i].l, &N[i].r, &N[i].a, &N[i].b, &N[i].c); V.pb(make_pair(2 * N[i].l , i)); V.pb(make_pair(2 * N[i].r , i)); V.pb(make_pair(2 * N[i].l + 1, -1)); V.pb(make_pair(2 * N[i].r + 1, -1)); N[i].l = N[i].r = -1; } int pos = 1; sort(V.begin(), V.end()); for (int i = 0; i < V.size(); i++) { if (V[i].Y == -1) { pos++; continue; } if (N[V[i].Y].l == -1) N[V[i].Y].l = pos; else N[V[i].Y].r = pos; if (i != V.size() - 1 && V[i].X == V[i+1].X) continue; pos++; } pos--; for (int i = 0; i < n; i++) { if (N[i].l - 1 >= 1) update(1, N[i].l - 1, N[i].c, 1, pos, 1); update(N[i].l, N[i].r, N[i].a, 1, pos, 1); if (N[i].r + 1 <= pos) update(N[i].r + 1, pos, N[i].b, 1, pos, 1); } printf("%I64d\n", query(1, pos, 1, pos, 1)); } return 0; }
剩下两题不会了= =,这场能升分得益于A题的错误贪心发现得早。。没造成太多罚时损失,遗憾是手速太慢没hack到人。B题知道做法,但是调线段树调了半天,还没注意到可以是实数,样例一直调不过,决定去刷下线段树专题,,补补线段树。
2017-01-23 22:09:00