洛谷 P6851 onu (貪心,模擬)
阿新 • • 發佈:2020-10-21
-
題意:C和D打牌,每張牌有花色和點數,小D剛開始的分數為\(v\),不管輸還是贏,只要小D出了牌(花色必須相同),就能得到那張牌點數的分數,若是贏了(點數不小於D的牌),他可以另外加\(c\)分,輸了就要扣\(c\)分,現在D知道了C的出牌情況,問他最多能拿多少分,並輸出出牌情況.
-
題解:首先,假如他兩的牌花色不同,那麼D一定打不出牌,只能白白\(-=c\),否則我們要儘可能的出多的牌,並且要贏得多,貪心策略是,用D的最大的牌去打掉C最大的牌,如果C同種顏色最小的牌都比D最大的大,那麼只能隨便打一張騙一點分並且把C的最大的牌消耗掉,實現起來挺複雜的,具體看程式碼吧.
-
程式碼:
struct misaka{ int col; int val; int id; bool operator < (const misaka &mikoto) const{ return val<mikoto.val; } bool operator > (const misaka &mikoto) const{ return val>mikoto.val; } }a[N],b[N]; int n,m,c; ll v; multiset<misaka> V[N]; int ans[N]; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n>>m>>c>>v; for(int i=1;i<=n;++i){ cin>>a[i].col>>a[i].val; a[i].val=-a[i].val; //存負數方便我們後面進行二分查詢 a[i].id=i; } for(int i=1;i<=m;++i){ ans[i]=-1; cin>>b[i].col>>b[i].val; b[i].val=-b[i].val; //存負數方便我們後面進行二分查詢 b[i].id=i; } sort(a+1,a+1+n); for(int i=1;i<=m;++i){ V[b[i].col].insert(b[i]); //記錄小C每種顏色的點數,set會對點數自動排序 } for(int i=1;i<=n;++i){ if(V[a[i].col].empty()) continue; v-=a[i].val; auto p=V[a[i].col].lower_bound(a[i]); //因為全是負數,找小C當前顏色牌中小於小D的牌 if(p==V[a[i].col].end()){ //小D最大的牌打不過小C最小的牌 v-=c; p=V[a[i].col].begin(); //隨便出一張 } else v+=c; //auto t=*p; ans[p->id]=a[i].id; //記錄ans V[a[i].col].erase(p); //彈出小C的一張牌 } for(int i=1;i<=m;++i){ if(ans[i]==-1) v-=c; } cout<<v<<endl; for(int i=1;i<=m;++i){ cout<<ans[i]<<endl; } return 0; }