1. 程式人生 > >SPOJ:One piece(最大匹配問題)(Gut Problem!)

SPOJ:One piece(最大匹配問題)(Gut Problem!)

這一 bit 估值 clu 排除 DC multipl contain any

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;
}

SPOJ:One piece(最大匹配問題)(Gut Problem!)