SPOJ:One piece(最大匹配问题)(Gut Problem!)
Posted ---学习ing---
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ:One piece(最大匹配问题)(Gut Problem!)相关的知识,希望对你有一定的参考价值。
One of DB and TN common interests is traveling. One day, they went to Grand Line and found One Piece !
The One Piece treasure has n gold coins (n is even). Both them like gold coins, but they evaluate them as different values. So they decided to divide those coins by following method :
DB and TN do n / 2 steps, at each step, DB choose 2 coins, TN takes the coin that she evaluates it greater, and DB take the rest coin.
Let’s help DB find how to take the maximum value at possible.
Input
First line : a single integer n (n is even) – the number of coins
Second line : n integers a1, a2, …, an. ai is the value of ith coin that TN evaluates.
Third line : n integers b1, b2, …, bn. bi is the value of ith coin that DB evaluates.
Output
First line : an integer S – the maximum value DB can take.
Last n / 2 lines : ith line contains two number x and y (1 ≤ x, y ≤ n), are the indexes of two
coins that DB choose on ith step. Each coin must be chose exact one time.
If there are multiple ways, just print any of them.
Constraints
2 ≤ n ≤ 500 000
1 ≤ ai ≤ 109
1 ≤ bi ≤ 109
Note that a1, a2, …, an are n distinct integers.
Example
Input: 6 6 10 11 18 5 14 1 7 6 12 15 1 Output: 28 5 1 2 6 3 4
Warning: large Input/Output data, be careful with certain languages
题意:有N个物品(N是偶数),对于每个物体,A同学和B同学都有自己的估值。每次A同学取出两个物体,B取走自己认为价值高的一个,然后A拿走剩下的一个,问A应该如果选择。使得A最后获得的价值最高。
思路:我们按B认为的价值排序,假设排成一排,左边大于右边,那么问题就成了:
错误思路:用优先队列,一开始把除了最右边的那个都放进队列里,从最右边开始匹配,找他左边的还没有被匹配的最小值匹配; 比如12 1 6 7 2 15。得到错误答案24。
正确打开方式:我们先假设把偶数的取走,然后如果右边的未取走的比它大,则可以替换。那么可以用单调队列搞。
#include<bits/stdc++.h> using namespace std; const int maxn=1000010; struct in{ int a,b,id; in(){ a=b=id=0;} in(int bb,int ii):b(bb),id(ii){} bool friend operator <(in x,in y){ return x.b>y.b; } }s[maxn]; bool cmp(in w,in v){ return w.a>v.a; } int vis[maxn]; set<in>Set; int L[maxn],R[maxn]; int main() { int N,i,j; long long ans=0; scanf("%d",&N); for(i=1;i<=N;i++) scanf("%d",&s[i].a); for(i=1;i<=N;i++) scanf("%d",&s[i].b); for(i=1;i<=N;i++) s[i].id=i; sort(s+1,s+N+1,cmp); for(i=N;i>=1;i--){ if(i%2==0){ if(Set.empty()) ans+=s[i].b,vis[s[i].id]=1; else { set<in>::iterator it=Set.begin(); if((*it).b>s[i].b){ ans+=(*it).b; vis[(*it).id]=1; Set.insert(in(s[i].b,s[i].id)); Set.erase(it); } else { vis[s[i].id]=1; ans+=s[i].b; } } } else Set.insert(in(s[i].b,s[i].id)); } int sum1=0,sum2=0; for(i=N;i>=1;i--){ if(vis[s[i].id]) L[++sum1]=s[i].id; else R[++sum2]=s[i].id; } printf("%lld\n",ans); for(i=1;i<=N/2;i++) printf("%d %d\n",L[i],R[i]); return 0; }
以上是关于SPOJ:One piece(最大匹配问题)(Gut Problem!)的主要内容,如果未能解决你的问题,请参考以下文章