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认为的价值排序,假设排成一排,左边大于右边,那么问题就成了:

           

 The problem:有N个人,从左到右排除一排,每个人有自己的权值,现在需要两两匹配成N/2队,每队的贡献是这一队的右边这个人的权值( 即在原题中左边的被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;
}

猜你喜欢

转载自www.cnblogs.com/hua-dong/p/9058008.html