HDU 4791 Alice's Print Service
从后往前预处理打印纸的最小花费。然后在询问时通过upper_bound找到位置p,比较当前打印纸张花费与相邻临界点最小花费即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <queue> #include <cmath> #include <set> using namespace std; int T; const int maxn = 100010; const int INF = 0x3f3f3f3f; typedef long long LL; LL x[maxn], y[maxn]; LL cost[maxn]; int main() { int T; for(scanf("%d", &T); T > 0; T--) { int n, m; scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { scanf("%I64d%I64d", &x[i], &y[i]); cost[i] = x[i]*y[i]; } LL pre = cost[n-1]; for(int i = n-1; i >= 0; i--) { if(pre < cost[i]) { cost[i] = pre; pre = cost[i]; } } while(m--) { LL q; scanf("%I64d", &q); if(q >= x[n-1]) { printf("%I64d\n", q*y[n-1]); continue ; } LL p = upper_bound(x, x+n, q)-x; LL ans = q*y[p-1]; ans = min(ans, cost[p]); printf("%I64d\n", ans); } } return 0; }
HDU 4950 Monster & HDU 4952 Number Transformation
多校第八场,做比赛还是不够稳呐!(=@__@=)!
4950:给定一个怪物,初始HP为h,战士攻击力为a,每次回合结束后怪物能回复b的血量,如果怪物的血量<1时,判负。战士经过K轮战斗必须休息一轮,问是否能杀死怪物。
贪心即可,首先判断一次杀死的情况,在判断a<=b,永远杀不死的情况,然后再在a>b的情况里分类判断,注意int越界。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <map> #include <cmath> #include <stack> using namespace std; typedef long long LL; LL h, a, b, k; int main() { int kase = 0; while(~scanf("%I64d%I64d%I64d%I64d", &h, &a, &b, &k)) { if(h == 0 && a == 0 && b == 0 && k == 0) break; printf("Case #%d: ", ++kase); if(a >= h) { printf("YES\n"); continue ; } if(a <= b) printf("NO\n"); else { LL T = h-a*k+b*(k-1); if(T <= 0) printf("YES\n"); else { LL M = h-a*k+b*(k+1); if(M >= h) printf("NO\n"); else printf("YES\n"); } } } return 0; }
4952:打表找规律,我找到的规律大约是在sqrt(n)左右后面的项与前面的项是等差数列,而且差值=等差数列的首项x/i(i-th operation),时间复杂度大约在O(sqrt(n)),对10^10次方左右的数据足够了。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <map> #include <cmath> #include <stack> using namespace std; typedef long long LL; LL work(LL x, LL i) { if(x%i == 0) return x; LL q = x/i*i+i; return q; } LL n, k; int main() { int kase = 0; while(~scanf("%I64d%I64d", &n, &k) && (n+k)) { LL x, y; x = n; LL i, a; LL b; for(i = 2; i <= k; i++) { y = x; x = work(x, i); a = x-y; b = x/i; if(x%i == 0 && a == b) break; } if(i <= k) x += (k-i)*b; printf("Case #%d: %I64d\n", ++kase, x); } return 0; }
HDU 4961 Magical Forest
大意:虚拟出一个2*10^9 * 2*10^9的数组内存空间,现在这个内存空间初始化为0,并且对其中的某些元素进行赋初值。后接着一系列的操作使得这个数组的行和列得以交换,中间还对某一行或者是某一列元素的值进行询问。
前段时间写过一个类似的题,二哥的内存。没想到在多校遇到了这道题,只不过数据范围改一下,但是有一个限制条件,即交换的两行(列)必须都有水果或者都没水果,注意这一点,用map映射一下值就可以了。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <map> using namespace std; map<long long int, int> mp; map<int, int> r, c; int n, m, k; void swap(int &a, int &b) { int t = a; a = b; b = t; } int main() { int T, kase = 0; for(scanf("%d", &T); T > 0; T--) { scanf("%d%d%d", &n, &m, &k); mp.clear(); r.clear(); c.clear(); for(int i = 0; i < k; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); mp[1LL*x*2000000005+y] = z; r[x] = x, c[y] = y; } int q; scanf("%d", &q); printf("Case #%d:\n", ++kase); while(q--) { int cmd, x, y; scanf("%d%d%d", &cmd, &x, &y); if(cmd == 1) { if(r.count(x) && r.count(y)) { swap(r[x], r[y]); } if(!r.count(x) && !r.count(y)) { r[x] = x, r[y] = y; swap(r[x], r[y]); } } else if(cmd == 2) { if(c.count(x) && c.count(y)) { swap(c[x], c[y]); } if((!c.count(x) && !c.count(y))) { c[x] = x, c[y] = y; swap(c[x], c[y]); } } else { if(mp[1LL*r[x]*2000000005+c[y]] != 0) { printf("%d\n", mp[1LL*r[x]*2000000005+c[y]]); } else printf("0\n"); } } } return 0; }
HDU 4930 Fighting the Landlords
给定斗地主的规则以及两幅手牌,然后判断是否在这一轮内你不会输给对手或者出完了全部手牌。
在比赛中我判断所有的情况,这样比较麻烦。其实可以把Bomb、Tri、Pair拆开分别去判断,有很多细节需要注意。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; int x[20], y[20]; int Win(int n) { if(n == 4 || n == 6) //炸弹带 { for(int i = 17; i >= 3; i--) { if(x[i] == 4) return 1; } } if(n == 5) //3带2 { int Tri = 0, Dou = 0; for(int i = 17; i >= 3; i--) { if(x[i] == 3) Tri = 1; if(x[i] == 2) Dou = 1; } if(Tri && Dou) return 1; } if(n == 4) //3带1 { for(int i = 17; i >= 3; i--) { if(x[i] == 3) return 1; } } if(n == 3) //三个 { for(int i = 17; i >= 3; i--) { if(x[i] == 3) return 1; } } if(n == 2) //Double { for(int i = 17; i >= 3; i--) { if(x[i] == 2) return 1; } } if(n == 1) return 1; //一个 return 0; } int main() { int T; for(scanf("%d", &T); T > 0; T--) { char s[20]; scanf("%s", s); memset(x, 0, sizeof(x)); memset(y, 0, sizeof(y)); for(int i = 0; s[i]; i++) { int t; if(s[i] == 'T') t = 10; else if(s[i] == 'J') t = 11; else if(s[i] == 'Q') t = 12; else if(s[i] == 'K') t = 13; else if(s[i] == 'A') t = 14; else if(s[i] == '2') t = 15; else if(s[i] == 'X') t = 16; else if(s[i] == 'Y') t = 17; else t = s[i]-'0'; x[t]++; } int len = strlen(s); scanf("%s", s); for(int i = 0; s[i]; i++) { int t; if(s[i] == 'T') t = 10; else if(s[i] == 'J') t = 11; else if(s[i] == 'Q') t = 12; else if(s[i] == 'K') t = 13; else if(s[i] == 'A') t = 14; else if(s[i] == '2') t = 15; else if(s[i] == 'X') t = 16; else if(s[i] == 'Y') t = 17; else t = s[i]-'0'; y[t]++; } if(x[16] == 1 && x[17] == 1) //有大小王 { printf("Yes\n"); continue; } if(Win(len)) { printf("Yes\n"); continue ; } //出完的情况 if(y[16] == 1 && y[17] == 1) //有大小王 { printf("No\n"); continue; } int bomb = -1, p; for(int i = 17; i >= 3; i--) //炸弹 { if(x[i] == 4) { bomb = 1; p = i; break; } } int win = 1; if(bomb == 1) { for(int i = 17; i > p; i--) { if(y[i] == 4) { win = 0; break; } } } if(bomb == 1 && win) { printf("Yes\n"); continue; } //有炸弹且最大 else if(!win) { printf("No\n"); continue ;} //有炸弹,但输了。 for(int i = 3; i <= 17; i++) if(y[i] == 4) { bomb = 2; break; } if(bomb == 2) { printf("No\n"); continue ; } //对手有炸弹,我没有。 win = 1; int Tri = -1; for(int i = 17; i >= 3; i--) //三个 { if(x[i] == 3) { Tri = 1; p = i; break; } } if(Tri == 1) { for(int i = 17; i > p; i--) { if(y[i] == 3) { Tri = 0; break; } } } if(Tri == 1) { printf("Yes\n"); continue ;} else if(Tri == 0) win = 0; int Dou = -1; for(int i = 17; i >= 3; i--) //两个 { if(x[i] == 2) { Dou = 1; p = i; break; } } if(Dou == 1) { for(int i = 17; i > p; i--) { if(y[i] == 2 || y[i] == 3) { Dou = 0; break; } } } if(Dou == 1) { printf("Yes\n"); continue ; } else if(Dou == 0) win = 0; int solo = -1; for(int i = 17; i >= 3; i--) //一个 { if(x[i] == 1) { solo = 1; p = i; break; } } if(solo == 1) { if(win == 0) win = 1; for(int i = 17; i > p; i--) { if(y[i] == 1 || y[i] == 2 || y[i] == 3) { win = 0; break; } } } if(win == 1) printf("Yes\n"); else if(win == 0) printf("No\n"); } return 0; }