799C(xjb)

题目链接: http://codeforces.com/problemset/problem/799/C

题意: 有c, d两种货币, 有 n 个货物, 可以用 c 货币或者 d 货币购买, 现在需要买两件货物, 问购买的货物的美丽值最大可为多少.

思路: 只买两件货物, 那么总共有 3 总可能, 买一件 c 一件 d, 买两件 c 或者买两件 d . 取他们的最大值即可.

可以给 c 货物和 d 货物按 p 升序排列, 那么对于买一件 c 一件 d 的情况, 只需要遍历一下 c 货物 和 d 货物, 分别取能买到的最大 b 值即可.

对于买两件 c 的情况,  用 vis[k] 存储当前 k 个 c 货币最大可买到的 b 值. 那么可以遍历c 货物的同时更新 vis 数组, 即对于当前 i , vis[k] 存储 [0, i) 中 k 可以买到的最大价值.

那么对于每一个 i , 匹配一下 vis[c - gel_c[i].p] 即可, 然后维护一下 gel_c[i].b + vis[c - gel_c[i].p] 的最大值即可.

对于选两件 d 的情况, 和选两个 c 的情况处理方法相同.

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #include <string.h>
 5 using namespace std;
 6
 7 const int MAXN = 1e5 + 10;
 8 struct node{
 9     int b, p;
10 }gel_c[MAXN], gel_d[MAXN];
11
12 int vis[MAXN], tag[MAXN];
13
14 bool cmp(node x, node y){
15     return x.p < y.p;
16 }
17
18 int main(void){
19     char op[5];
20     int n, c, d, indx_c = 0, indx_d = 0, ans = 0;
21
22     scanf("%d%d%d", &n, &c, &d);
23     for(int i = 0; i < n; i++){
24         int b, p;
25         scanf("%d%d%s", &b, &p, op);
26         if(op[0] == ‘C‘){
27             gel_c[indx_c].b = b;
28             gel_c[indx_c++].p = p;
29         }else{
30             gel_d[indx_d].b = b;
31             gel_d[indx_d++].p = p;
32         }
33     }
34
35     sort(gel_c, gel_c + indx_c, cmp);
36     sort(gel_d, gel_d + indx_d, cmp);
37
38     int cnt1 = 0, cnt2 = 0, pos = 0;
39     for(int i = 0; i < indx_c; i++){
40         if(gel_c[i].p > c) break;
41         cnt1 = max(cnt1, gel_c[i].b);
42     }
43     for(int i = 0; i < indx_d; i++){
44         if(gel_d[i].p > d) break;
45         cnt2 = max(cnt2, gel_d[i].b);
46     }
47     if(cnt1 && cnt2) ans = cnt1 + cnt2;
48
49     cnt1 = cnt2 = 0;
50     for(int i = 0; i < indx_c; i++){
51         int gg = c - gel_c[i].p;
52         if(gg <= 0) break;
53         int cc = upper_bound(tag, tag + pos, gg) - tag;
54         if(cc == 0 && i != 0) break;
55         cc = tag[cc - 1];
56         if(vis[cc]) ans = max(ans, gel_c[i].b + vis[cc]);
57         vis[gel_c[i].p] = max(cnt1, gel_c[i].b);
58         tag[pos++] = gel_c[i].p;
59         cnt1 = max(cnt1, gel_c[i].b);
60     }
61
62     pos = 0;
63     for(int i = 0; i < indx_d; i++){
64         int gg = d - gel_d[i].p;
65         if(gg <= 0) break;
66         int cc = upper_bound(tag, tag + pos, gg) - tag;
67         if(cc == 0 && i != 0) break;
68         cc = tag[cc - 1];
69         if(vis[cc]) ans = max(ans, gel_d[i].b + vis[cc]);
70         vis[gel_d[i].p] = max(cnt2, gel_d[i].b);
71         tag[pos++] = gel_d[i].p;
72         cnt2 = max(cnt2, gel_d[i].b);
73     }
74     printf("%d\n", ans);
75     return 0;
76 }

时间: 2024-08-29 09:15:27

799C(xjb)的相关文章

hdu_5881_Tea(xjb猜)

题目链接:hdu_5881_Tea 题意: 有一壶水, 体积在 L 和 R 之间, 有两个杯子, 你要把水倒到两个杯子里面, 使得杯子水体积几乎相同(体积的差值小于等于1), 并且使得壶里剩下水体积不大于1. 你无法测量壶里剩下水的体积, 问最小需要倒水的次数. 题解: 我是xjb猜的,下面附上ICPCcamp的题解 考虑倒水的大致过程,L = 0 和 L = 1 的情况应该是等价的,所以不妨设 L >0.首先向一个杯子倒 L/2升水,再往另一个杯子倒 L/2+1升水.接下来就来回往两个杯子里倒

51nod1276(xjb)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1276 题意:中文题诶- 思路:xjb 通过画图可以发现对于当前水没过的点,若其为极小值点,则岛屿数目-1,若为极大值点则岛屿数目+1: 可以给海面高度排序,海面高度单调时岛屿的状态也是连续的. 可以给山峰高度排序,避免对于每一个高度海面都遍历一遍才能找到被淹没的山峰. 代码: 1 #include <iostream> 2 #include <stdi

51nod1770(xjb)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1770 题意:中文题诶- 思路:随便写几个例子不难发现乘机中间部分会出现循环,只需考虑3个a的情况即可... 代码: 1 #include <iostream> 2 using namespace std; 3 4 int main(void){ 5 int t, a, b, d, n; 6 cin >> t; 7 while(t--){ 8 ci

hdu_5927_Auxiliary Set(xjb搞)

题目链接:hdu_5927_Auxiliary Set 题意: 给一棵n个节点的树,最开始全部都是重点,现在有q个询问,每次给你一些轻点,并叫你输出整棵树的重点数量, 轻点可能会变为重点,如果这个轻点是两个重点的lca. 题解: 这里 我把有重点的子树叫重子树,一个重点都没有的子树叫轻子树. 一个轻点如果有两个重子树,那么这个轻点就会变为重点,可以画图试试. 然后我们就将轻点从树的最底层开始更新 x为这个点的子树个数,n为这个点的轻子树个数, 如果x-n=0,那么这个点的父亲节点的n就++ 如果

hdu_5805_NanoApe Loves Sequence(xjb搞)

题目链接:hdu_5805_NanoApe Loves Sequence 题意: 给你n个数,现在要删一个数,删每个数的概率是一样的,现在问你删一个值后的相邻数绝对值最大差的期望是多少,因为担心精度误差,让你答案乘n 题解: 先算出不删数的绝对值最大的差ma并记录位置,如果要删的数不是刚才求出来的位置,那么ans+=max(abs(a[i-1]-a[i+1],ma).如果是,那么重新求一下最大值就行了,因为最多重求两次,所以总复杂度还是O(n). 1 #include<cstdio> 2 #i

【玲珑杯Round17】xjb总结

zcy真是垃圾,啥都不会的那种. 菜的不行. 这场手速上了三题,然后各种E被卡-- 日个吗居然E不开栈,傻逼吧 有毒吧 来看题: A.sqc给的我的神奇公式,gtmd居然能A? #include<bits/stdc++.h> using namespace std; int n;double ans=0; int main(){ scanf("%d",&n); for(int i=1;i<n-1;i++){ int j=(n-i)/2,k=(n-i)-(n-i

计蒜课/ 微软大楼设计方案/中等(xjb)

题目链接:https://nanti.jisuanke.com/t/15772 题意:中文题诶- 思路:对于坐标为p1(x1, y1), p2(x2, y2) 的两个核心, 其中 x1 <= x2 用 d(p1, p2) 表示两者间最矮的大楼,则需要时间为: 对于d(p1, p2) >= min(y1, y2)情况,cnt = abs(x2 - x1) + abs(y2 - y1) 对于d(p1, p2) < min(y1, y2)情况,cnt = y1 + y2 - 2*d(p1, p

51nod1112(xjb)

題目鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1112 題意:中文題誒- 思路:對於函數 f(x) = a + kx,對於x足夠大的情況下,顯然f(x)的值的相對大小是只受 k 影響的.對於 n 條這樣的直線最多可以發生 (n-1)*n/2 次超越: 不過本題只要求輸出前 1e4 次超越,所以可以先二分出1e4次超越的時間點(這部分是用來優化常數的),然後再枚舉每一次超越即可.這樣的時間復雜 度爲 O(n^2

51nod1110(xjb)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1110 题意:中文题诶- 思路:可以将在 xi 位置,权值为 wi 的点看作有 wi 个点在 xi 位置.然后再按位置排一下序,再找中位数即可: 代码: 1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #define ll long long 5 u