USACO[CowCoupons] 喜欢ヅ旅行 2023-06-02 11:57 16阅读 0赞 [USACO\[CowCoupons\]][USACO_CowCoupons] 这题是个非常棒的贪心题,唯一的缺点是数据太水了,强烈要求加强数据.(当然我知道在这里喊不会有人鸟我...) 这个题相信有些人的第一思路是按优惠后价格排序,能买就买,但这显然是错误的. 比如你有两头牛和一张优惠券,两头牛优惠前和优惠后的价格分别是\\(\{50,1\}\\)和\\(\{10000,25\}\\). 这样应该很显然. 那我们就可以考虑去在哪些牛身上用优惠券是最值的.一个思路是先按上面的做法取\\(k\\)头牛,然后再对剩下的牛逐一考虑是否把优惠券用到这头牛上更优. 一个非常简单的思路是回溯,但这显然不太行是叭...复杂度上天系列. 那我们考虑,一头牛相比另一头牛使用优惠券更优的条件是如何的. 不难发现,如果对于两头牛\\(i,j\\),有\\\[c\_i+p\_j < c\_j + p\_i\\\]那么显然把优惠券使用在\\(i\\)这头牛会比较优. 那么移一下项,发现这个东西变成了这个\\\[p\_i - c\_i > p\_j - c\_j\\\],所以我们把之前每个先钦定使用优惠券的牛的这个东西压入小根堆中,再逐一考虑后面的牛即可. 不过判断的时候我还是用了最开始的结论.需要注意的是,在考虑后几头牛的时候,要按原价排一遍序,因为如果没有优惠券了,而你还有钱,显然这样买比较优. \\(Code:\\) #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <string> #include <vector> #include <queue> #include <cmath> #include <map> #define MEM(x,y) memset ( x , y , sizeof ( x ) ) #define rep(i,a,b) for (int i = a ; i <= b ; ++ i) #define per(i,a,b) for (int i = a ; i >= b ; -- i) #define int long long #define pii pair < int , int > #define X first #define Y second using std::pair ; using std::max ; using std::min ; using std::priority_queue ; using std::vector ; const int N = 5e4 + 100 ; priority_queue < pii , vector < pii > , std::greater < pii > > q ; int n , k , m , tot , ans ; pii cow[N] ; inline bool cmp (pii a , pii b) { if ( a.Y != b.Y ) return a.Y < b.Y ; return a.X < b.X ; } signed main () { scanf ("%lld%lld%lld" , & n , & k , & m ) ; ans = tot = 0 ; rep ( i , 1 , n ) scanf ("%lld%lld" , & cow[i].Y , & cow[i].X ) ; // P C std::sort ( cow + 1 , cow + n + 1 ) ; rep ( i , 1 , k ) { tot += cow[i].X ; ++ ans ; if ( tot > m ) { printf ("%lld\n" , i - 1 ) ; return 0 ; } q.push ( { cow[i].Y - cow[i].X , i } ) ; } ans = k ; std::sort ( cow + k + 1 , cow + n + 1 , cmp ) ; rep ( i , k + 1 , n ) { pii tmp = q.top () ; if ( cow[tmp.Y].X + cow[i].Y > cow[tmp.Y].Y + cow[i].X ) { ++ ans ; tot -= cow[tmp.Y].X ; tot += ( cow[i].X + cow[tmp.Y].Y ) ; q.pop () ; q.push ( { cow[i].Y - cow[i].X , i } ) ; } else { ++ ans ; tot += cow[i].Y ; } if ( tot > m ) { printf ("%lld\n" , ans - 1 ) ; return 0 ; } } printf ("%lld\n" , n ) ; system ("pause") ; return 0 ; } 转载于:https://www.cnblogs.com/Equinox-Flower/p/11402156.html [USACO_CowCoupons]: https://www.luogu.org/problem/P3045
还没有评论,来说两句吧...