题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=853
E:
给定二维平面上的n个点,画一个矩形,使得矩形内部和矩形边界上的点权值和最大。
对所有点离散化之后枚举矩形的左边界,维护右边的点不停加进来的答案。
1 /* basic header */ 2 #include3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 2e3 + 10; 21 struct Point { 22 int x, y, c; 23 bool operator<(const Point &rhs)const { 24 return x < rhs.x || (x == rhs.x && y < rhs.y); 25 } 26 } p[maxn]; 27 28 struct Node { 29 ll sum, maxv, prev, sufv; 30 } segt[maxn << 2]; 31 32 void maintain(int curpos) { 33 segt[curpos].sum = segt[lson].sum + segt[rson].sum; // 总和 34 segt[curpos].maxv = max(segt[lson].maxv, segt[rson].maxv); // 答案 35 segt[curpos].maxv = max(segt[curpos].maxv, segt[lson].sufv + segt[rson].prev); //不拿当前的点 36 segt[curpos].prev = max(segt[lson].prev, segt[lson].sum + segt[rson].prev); // 最大前缀和 37 segt[curpos].sufv = max(segt[lson].sufv + segt[rson].sum, segt[rson].sufv); // 最大后缀和 38 } 39 40 void build(int curpos, int curl, int curr) { 41 if (curl == curr) { 42 segt[curpos].maxv = segt[curpos].prev = segt[curpos].sufv = segt[curpos].sum = 0; 43 return; 44 } 45 int mid = curl + curr >> 1; 46 build(lson, curl, mid); build(rson, mid + 1, curr); 47 maintain(curpos); 48 } 49 50 void update(int pos, int curpos, int curl, int curr, ll v) { 51 if (curl == curr) { 52 segt[curpos].sum += v; 53 segt[curpos].maxv = segt[curpos].prev = segt[curpos].sufv = max(0ll, segt[curpos].sum); // 不拿就是0 54 return; 55 } 56 int mid = curl + curr >> 1; 57 if (pos <= mid) update(pos, lson, curl, mid, v); 58 else update(pos, rson, mid + 1, curr, v); 59 maintain(curpos); 60 } 61 62 int main() { 63 int t; scanf("%d", &t); 64 while (t--) { 65 vector<int>keyX, keyY; 66 int n; scanf("%d", &n); ll ans = 0; 67 for (int i = 0; i < n; i++) { 68 scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].c); 69 keyX.pb(p[i].x); keyY.pb(p[i].y); 70 } 71 sort(keyX.begin(), keyX.end()); 72 sort(keyY.begin(), keyY.end()); 73 int totalX = unique(keyX.begin(), keyX.end()) - keyX.begin(); 74 int totalY = unique(keyY.begin(), keyY.end()) - keyY.begin(); 75 // 把点的xy值都离散化 76 for (int i = 0; i < n; i++) { 77 p[i].x = lower_bound(keyX.begin(), keyX.begin() + totalX, p[i].x) - keyX.begin() + 1; 78 p[i].y = lower_bound(keyY.begin(), keyY.begin() + totalY, p[i].y) - keyY.begin() + 1; 79 } 80 sort(p, p + n); // 先按x然后按y排序 81 // 遍历totalX条边,相当于枚举矩形左边界 82 for (int i = 0; i < totalX; i++) { 83 int x = i + 1, tmp = 0; 84 while (tmp < n && p[tmp].x < x) tmp++; // 找到在当前点在p数组中的位置 85 build(1, 1, totalY); //建立空线段树 86 while (tmp < n) { //扫一遍点, 计算后面所有x相同的点 87 int curx = p[tmp].x; 88 while (tmp < n && p[tmp].x == curx) { 89 update(p[tmp].y, 1, 1, totalY, p[tmp].c); 90 tmp++; 91 } 92 ans = max(ans, segt[1].maxv); 93 } 94 } 95 printf("%lld\n", ans); 96 } 97 return 0; 98 }
H:
打表发现答案随着k浮动,总是出现在k的周围。
枚举区间[k-500,k+500]之内的答案逐一验证即可。
1 #include2 #include 3 #include 4 using namespace std; 5 typedef long long ll; 6 7 ll f(ll n, ll m) { 8 ll tot = 0; 9 for (ll x = n + 1;; x++) { 10 if (__gcd(n, x) == 1) { 11 tot ++ ; 12 if (tot == m) { 13 return x; 14 } 15 } 16 } 17 } 18 19 int main() { 20 int T; cin >> T; 21 while (T--) { 22 ll k, m; 23 cin >> k >> m; 24 int flag = 0; 25 for (ll n = max(2ll, k - 500ll); n <= k + 500ll; n++) { 26 if ((f(n, m)) - n == (n ^ k)) { 27 cout << n << endl; 28 flag = 1; 29 break; 30 } 31 } 32 if (!flag) puts("-1"); 33 } 34 return 0; 35 }
L:
显然两个人轮流取最大的,搞个大根堆就完事了。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 typedef long long ll; 7 int main() { 8 int T; scanf("%d", &T); 9 while (T--) { 10 int n; 11 scanf("%d", &n); 12 priority_queue<int>Q; 13 while (!Q.empty()) Q.pop(); 14 for (int i = 1; i <= n; i++) { 15 int x; scanf("%d", &x); 16 Q.push(x); 17 } 18 ll ans[2]; ans[0] = ans[1] = 0LL; 19 int fg = 0; 20 while (!Q.empty()) { 21 ans[fg] += Q.top(); 22 Q.pop(); 23 fg = 1 - fg; 24 } 25 printf("%lld %lld\n", ans[0], ans[1]); 26 } 27 return 0; 28 }