板刷贪心总结
AT_agc029_a [AGC029A] Irreversible operation(橙)
为什么我自己没有做出来
其实这道题就是求逆序对的个数
那就从后往前遍历,统计遇到的 W 个数,遇到 B 就将答案加上 W 的个数
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
//不开long long 见祖宗
int n, w, ans;
string s;
signed main()
{
cin >> s;
s = " " + s;
n = s.size() - 1;
for(int i = n; i >= 1; i --)
{
if(s[i] == 'W')
{
w ++;
}
if(s[i] == 'B')
{
ans += w;
}
}
cout << ans << endl;
}
P2949 [USACO09OPEN] Work Scheduling G(蓝)
反悔贪心
按照人类逻辑,给截止时间从小到大排个序,优先做紧急的事情,在紧急的事情中优先完成报酬高的事情
但是万一后面的事情全都是报酬高的人类逻辑就不是最优的了
于是我们开始反悔,不做之前做过的事情中报酬最低的那个以完成报酬高的任务,可以用一个小根堆维护报酬
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
struct node
{
int val, t;
}a[100005];
priority_queue<int, vector<int>, greater<int> > q;
bool cmp(node x, node y)
{
return x.t < y.t;
}
signed main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> a[i].t >> a[i].val;
}
sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i ++)
{
if(q.size() < a[i].t)
{
q.push(a[i].val);
}
else if(q.top() < a[i].val)
{
q.pop();
q.push(a[i].val);
}
}
int ans = 0;
while(!q.empty())
{
ans += q.top();
q.pop();
}
cout << ans << endl;
}
P2209 [USACO13OPEN] Fuel Economy S(蓝)
先给所有加油站到起点的距离从小到大排个序
先考虑不能到达的情况
- 第一个加油站到起点的距离 > 初始油量
- 途中存在两个加油站之间的距离 > 油箱容量
- 最后一个加油站到终点的距离 > 油箱容量
排除不可能到达的情况后再进行贪心
-
加满足够的油,刚好跑到能跑到的第一个比现在这个加油站便宜的加油站
-
如果在加满油能跑到的范围内没有比当前加油站便宜的加油站,就在当前加油站加满油跑到能跑到的范围内最便宜的加油站
需要注意的一点是不能在判断 1 中跑到当前最便宜的加油站,而是看到一个便宜就跑过去 (我在这里卡了好久
然后就做完这道题了QAQ
P2431 正妹吃月饼(绿)
把 \(b\) 进行二进制拆分以后,对于每个位的1,我们可以把它去掉,然后直接把比它低的位全置1(将大的月饼分割成之前的小月饼)。
从高到低枚举1,当第一次产生的新数比A大时,就可以得出答案
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a, b, _, len, ans;
int cal(int x)
{
int cnt = 0;
while (x)
{
x -= x & -x;
cnt++;
}
return cnt;
}
signed main()
{
cin >> a >> b;
_ = b;
while (_)
{
len++;
_ >>= 1;
}
ans = max(cal(b), ans);
int qwq = 1;
for (int i = len; i; i--)
{
if ((b >> i - 1) & 1)
{
int t = b ^ (qwq << i - 1);
t |= (qwq << i - 1) - 1;
if (t >= a)
{
ans = max(cal(t), ans);
}
}
}
cout << ans << endl;
}
[P3045 [USACO12FEB] Cow Coupons G]([P3045 USACO12FEB] Cow Coupons G - 洛谷)
题意
FJ 准备买一些新奶牛。市场上有 \(N\) 头奶牛,第 \(i\) 头奶牛价格为 \(P_i\)。FJ 有 \(K\) 张优惠券,使用优惠券购买第 \(i\) 头奶牛时价格会降为 \(C_i\),当然每头奶牛只能使用一次优惠券。FJ 想知道花不超过 \(M\) 的钱最多可以买多少奶牛?
- \(1 \le K \le N \le 5 \times 10^4\)
思路
我们考虑先买下所有 \(C\) 最小的奶牛。
接着考虑反悔的条件,记用优惠券买的奶牛为 \(j\) ,当前奶牛为 \(i\)。如果用优惠券买当前奶牛加上用原价买 \(j\) 小于用优惠券买 \(j\) 加上原价买 \(i\),就可以反悔。于是可以得到反悔的如下等式:$$C_j + P_i > P_j + C_i$$
移向变为:\(P_j - C_j < P_i - C_i\)
所以我们把奶牛按照 \(P_i - C_i\) 排序就可以正常反悔贪心了
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e4 + 5;
struct COW
{
int p, c;
}a[N];
struct node
{
int data, id;
// bool operator<(const node it)const
// {
// return data < it.data;
// }
bool operator>(const node it)const
{
return data > it.data;
}
};
priority_queue<node, vector<node>, greater<node> > q1, q2;
priority_queue<int, vector<int>, greater<int> > q3;
int n, k, m, sum, ans, vis[N];
signed main()
{
cin >> n >> k >> m;
for(int i = 1; i <= n; i ++)
{
cin >> a[i].p >> a[i].c;
q1.push({a[i].p, i});
q2.push({a[i].c, i});
}
for(int i = 1; i <= k; i ++)
{
q3.push(0);
}
while(!q1.empty())
{
node x1 = q1.top();
node x2 = q2.top();
if(vis[x1.id])
{
q1.pop();
continue;
}
if(vis[x2.id])
{
q2.pop();
continue;
}
if(x1.data < x2.data + q3.top())
{
if(sum + x1.data > m)
{
break;
}
vis[x1.id] = 1;
q1.pop();
sum += x1.data;
ans ++;
}
else
{
if(sum + x2.data + q3.top() > m)
{
break;
}
sum += x2.data + q3.top();
ans ++;
q2.pop();
vis[x2.id] = 1;
q3.pop();
q3.push(a[x2.id].p - a[x2.id].c);
}
}
cout << ans << endl;
}
[P2107 小 Z 的 AK 计划](P2107 小 Z 的 AK 计划 - 洛谷)
题意
机房一条街有 \(n\) 个机房,第 \(i\) 个机房的坐标为 \(x_i\),从 \(x_1\) 到 \(x_2\) 所耗费的时间为 \(|x_1 - x_2|\),初始在 \(0\) 位置。小 Z 到达第 \(i\) 个机房后,可以花 \(t_i\) 的时间AK。当然,也可以过机房而不入。
小 Z 现在只有 \(m\) 个单位时间,现在他想知道自己最多能在多少个机房 AK。
\(1 \leq n \leq 10^5\),\(0 \leq m,x_i \leq 10^{18}\),\(0 \leq t_i \leq 10^9\)。
思路
考虑反悔贪心。每到达一个机房就AK,如果时间超过了就把需要时间最大的机房给取消AK,返还时间,直到时间不超过为止。
注意事项
- 初始位置是 \(0\)
- 要按 \(x_i\) 排序
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, m, ans, now, lst, cnt;
struct node
{
int x, t;
}a[100005];
priority_queue<int, vector<int>, greater<int> > q;
signed main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i].x >> a[i].t;
sort(a + 1, a + n + 1, [](node a, node b) { return a.x < b.x; });
for(int i = 1; i <= n; i ++)
{
now += a[i].x - lst;
lst = a[i].x;
q.push(a[i].t);
ans ++;
now += a[i].t;
while(!q.empty() && now > m)
{
ans --;
now -= q.top();
q.pop();
}
if(now > m)
break;
cnt = max(cnt, ans);
}
cout << cnt << endl;
}

浙公网安备 33010602011771号