2019HDU多校 Round10
Solved:3
Rank:214
08 Coin
题意:n组硬币 每组有两个 分别有自己的价值 每组的第一个被拿了之后才能拿第二个
问拿1,2....2n个硬币的最大价值
题解:之前贪心带反悔的做法写不出来... 然后学习下别人的贪心策略 考虑从0或1开始 每次拿两个
那么要么是拿一组 要么是拿两个散装最大的 然后模拟一下
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5; int a[MAXN], b[MAXN], vis[MAXN], vvis[MAXN], now;
int ans[MAXN << 1];
struct node {
int a, b, id; friend bool operator < (node A, node B) {
if(A.a + A.b == B.a + B.b) return A.id < B.id;
else return A.a + A.b < B.a + B.b;
}
};
node sum[MAXN];
priority_queue<node> que; void solve(int i) {
node tmp1 = {0, 0, 0}, tmp2 = {0, 0, 0}, tmp3 = {0, 0, 0};
while(now >= 1 && vis[now]) now--;
if(now >= 1) tmp1 = sum[now]; while(!que.empty() && vvis[que.top().id]) que.pop();
if(!que.empty()) tmp2 = que.top(), que.pop();
while(!que.empty() && vvis[que.top().id]) que.pop();
if(!que.empty()) tmp3 = que.top(), que.pop(); if(tmp1.a + tmp1.b > tmp2.a + tmp2.b + tmp3.a + tmp3.b) {
ans[i] = ans[i - 2] + tmp1.a + tmp1.b;
vis[now] = 1; vvis[now] = 1;
que.push(tmp2); que.push(tmp3);
} else {
ans[i] = ans[i - 2] + tmp2.a + tmp2.b + tmp3.a + tmp3.b;
if(tmp2.a) {
vis[tmp2.id] = 1;
que.push((node){0, sum[tmp2.id].b, tmp2.id});
} else vvis[tmp2.id] = 1;
if(tmp3.a) {
vis[tmp3.id] = 1;
que.push((node){0, sum[tmp3.id].b, tmp3.id});
} else vvis[tmp3.id] = 1;
}
} int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d%d", &a[i], &b[i]), sum[i].a = a[i], sum[i].b = b[i], sum[i].id = i, vis[i] = vvis[i] = 0;
sort(sum + 1, sum + 1 + n); now = n;
while(!que.empty()) que.pop();
ans[0] = 0;
for(int i = 1; i <= n; i++) que.push((node){sum[i].a, 0, i});
for(int i = 2; i <= n * 2; i += 2) solve(i); while(!que.empty()) que.pop();
now = n;
for(int i = 1; i <= n; i++) que.push((node){sum[i].a, 0, i}), vis[i] = vvis[i] = 0;
node t1 = que.top(); que.pop();
ans[1] = t1.a; que.push((node){0, sum[t1.id].b, t1.id}); vis[t1.id] = 1;
for(int i = 3; i <= n * 2; i += 2) solve(i); for(int i = 1; i <= n * 2; i++) {
if(i != n * 2) printf("%d ", ans[i]);
else printf("%d\n", ans[i]);
}
}
return 0;
}
Coin
11 Make Rounddog Happy (启发式分治)
题意:1e5个数 统计多少个区间满足 区间最大 - 区间长度 <= k 且区间内没有相同的数
题解:都说这个题是这种套路.... 用st表预处理区间最大值 然后再预处理每个数往左往右没有相同数的最远距离
然后每次找到区间最大值 暴力从区间小的一边枚举答案 然后分治
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 5;
ll ans;
int n, K;
int a[MAXN];
int st[MAXN][21], lg[MAXN];
int L[MAXN], R[MAXN];
int vis[MAXN]; void solve(int l, int r) {
if(l > r) return; int k = lg[r - l + 1];
int pos;
if(a[st[l][k]] >= a[st[r - (1 << k) + 1][k]]) pos = st[l][k];
else pos = st[r - (1 << k) + 1][k]; if(pos - l <= r - pos) {
for(int i = l; i <= pos; i++) { //枚举左端点
int rr = a[pos] - K + i - 1; //移项之后 满足rr <= 区间右端点就是满足题意的
rr = max(rr, pos); //大于pos 最大值才成立 int tr = min(R[i], r);
if(tr >= rr) ans += 1LL * (tr - rr + 1);
}
} else {
for(int i = r; i >= pos; i--) {
int ll = K - a[pos] + i + 1;
ll = min(ll, pos); int tl = max(L[i], l);
if(tl <= ll) ans += 1LL * (ll - tl + 1);
}
}
solve(l, pos - 1); solve(pos + 1, r);
} int main() {
lg[0] = -1;
for(int i = 1; i <= MAXN - 2; i++) lg[i] = lg[i >> 1] + 1; int T;
scanf("%d", &T);
while(T--) {
ans = 0;
scanf("%d%d", &n, &K);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), st[i][0] = i; for(int i = 1; i <= 20; i++)
for(int j = 1; j <= n + 1 - (1 << i); j++) {
if(a[st[j + (1 << (i - 1))][i - 1]] >= a[st[j][i - 1]]) st[j][i] = st[j + (1 << (i - 1))][i - 1];
else st[j][i] = st[j][i - 1];
} memset(vis, 0, sizeof(vis)); L[1] = 1; vis[a[1]] = 1;
for(int i = 2; i <= n; i++) {
if(vis[a[i]]) L[i] = max(L[i - 1], vis[a[i]] + 1);
else L[i] = L[i - 1];
vis[a[i]] = i;
} memset(vis, 0, sizeof(vis)); R[n] = n; vis[a[n]] = n;
for(int i = n - 1; i >= 1; i--) {
if(vis[a[i]]) R[i] = min(R[i + 1], vis[a[i]] - 1);
else R[i] = R[i + 1];
vis[a[i]] = i;
}
solve(1, n);
printf("%lld\n", ans);
}
return 0;
}
Make Rounddog Happy
2019HDU多校 Round10的更多相关文章
- HDU6578 2019HDU多校训练赛第一场 1001 (dp)
HDU6578 2019HDU多校训练赛第一场 1001 (dp) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题意: 你有n个空需要去填,有 ...
- HDU6579 2019HDU多校训练赛第一场1002 (线性基)
HDU6579 2019HDU多校训练赛第一场1002 (线性基) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6579 题意: 两种操作 1.在序列末 ...
- 2019HDU多校第一场1001 BLANK (DP)(HDU6578)
2019HDU多校第一场1001 BLANK (DP) 题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能 ...
- 2019HDU多校训练第三场 Planting Trees 暴力 + 单调队列优化
题意:有一个n * n的网格,每个网格中间有一颗树,你知道每棵树的高,你可以选择一个矩形区域把里面的树都围起来,但是矩形区域里面任意两棵树的高度差的绝对值不超过m,问这个矩形的最大面积是多少? 思路: ...
- 2017多校Round10(hdu6171~hdu6181)
补题进度:5/11 1001(双向BFS) 题意: 给你一个类似移子游戏,给你初始状态和终止状态,问初始状态到终止状态至少要移多少步,如果步数>20就-1 分析: 很明显的BFS了,不过普通的B ...
- 2019HDU多校第九场 Rikka with Quicksort —— 数学推导&&分段打表
题意 设 $$g_m(n)=\begin{cases}& g_m(i) = 0, \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ...
- 2019HDU多校第7场——构造
题意 假设现在你在准备考试,明天的考试有 $n$ 道题目,对于分值为 $i$ 的题目至少复习 $i+1$ 小时才能做对,已知总分为$m$,求确保完成 $k$ 道题的最少时间. 分析 手动尝试一下,发现 ...
- 2019HDU多校第六场1009 Three Investigators——杨表
题意 给定一个 n 个元素的数列,从前 k 个元素中取5次不下降子序列,求取得的和的最大值(k从1至n) 分析 考虑将数字 a[i] 拆成 a[i] 个 a[i],比如 “4,1,2”→“4,4,4, ...
- 2019HDU多校第六场 6641 TDL——乱搞&&思维题
题意 设 $f(n, m)$ 为大于 $n$ 且与 $n$ 互质的数中第 $m$ 小的数,求满足 $(f(n, m) - n) \oplus n = k$ 的最小正整数 $n$ 分析 因为 $m \l ...
随机推荐
- Oracle控制文件多路复用以及Oracle备份重建控制文件
控制文件中记录了oracle数据库的物理结构,也就是记录了数据库数据文件和日志文件的位置,控制文件中还记录了多种SCN,用这些SCN来确定数据文件和日志文件是否是正确的.如果不正确那么数据库就需要恢复 ...
- C#处理医学图像(二):基于Hessian矩阵的医学图像增强与窗宽窗位
根据本系列教程文章上一篇说到,在完成C++和Opencv对Hessian矩阵滤波算法的实现和封装后, 再由C#调用C++ 的DLL,(参考:C#处理医学图像(一):基于Hessian矩阵的血管肺纹理骨 ...
- 面试官:你真的了解Redis分布式锁吗?
什么是分布式锁 说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程.性能高的特点,它还经常被用于做分布式锁. 锁我们都知道,在程序中的作用就是同步工具,保证共享资源在同 ...
- LeetCode202. 快乐数
题目 编写一个算法来判断一个数 n 是不是快乐数. 快乐数定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1, 也可能是 无限循环 但始终变不到 ...
- ctfhub技能树—RCE—过滤空格
打开靶机 查看页面信息 开始尝试注入 127.0.0.1 || ls 尝试绕过 127.0.0.1||ls 使用cat命令查看flag 127.0.0.11||cat<flag_10872536 ...
- 02_Python基础
2.1 第一条编程语句 print("Hello, Python!") print("To be, or not to be, it's a question." ...
- 浅谈java中线程和操作系统线程
在聊线程之前,我们先了解一下操作系统线程的发展历程,在最初的时候,操作系统没有进程线程一说,执行程序都是串行方式执行,就像一个队列一样,先执行完排在前面的,再去执行后面的程序,这样的话很多程序的响应就 ...
- C#高级编程第11版 - 第六章 索引
[1]6.2 运算符 1.&符在C#里是逻辑与运算.管道符号|在C#里则是逻辑或运算.%运算符用来返回除法运算的余数,因此当x=7时,x%5的值将是2. [2]6.2.1 运算符的简写 1.下 ...
- 一个关于时区的bug
起因: 在 Apollo 中配置了某活动的开始时间是 2020-05-15, 代码中的逻辑判断如下: const nowTime = new Date().getTime(); const start ...
- C++ Primer Plus读书笔记(五)循环和关系表达式
1.前缀运算符的优先级是从右到左,例如: 1 *++p; //这句话的含义是先对p进行++,再取* 2.循环 c++11新增了一种循环方式,有点和python类似,如下: 1 array<int ...