2019 HDOJ Multi-University Training Contest Stage 6(杭电多校)

题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=853


E:

给定二维平面上的n个点,画一个矩形,使得矩形内部和矩形边界上的点权值和最大。

对所有点离散化之后枚举矩形的左边界,维护右边的点不停加进来的答案。

 1 /* basic header */
 2 #include <bits/stdc++.h>
 3 /* 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;i<b;++i)
11 #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 }
View Code

H:

打表发现答案随着k浮动,总是出现在k的周围。

枚举区间[k-500,k+500]之内的答案逐一验证即可。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 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 }
Code via. rsqppp 

L:

显然两个人轮流取最大的,搞个大根堆就完事了。

 1 #include<cstdio>
 2 #include<queue>
 3 #include<iostream>
 4 #include<vector>
 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 }
Code via. rsqppp

 

转载于:https://www.cnblogs.com/JHSeng/p/11318231.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值