Gym - 100513B:Colored Blankets (构造)

题意:给定N的棒棒,K种颜色,每个棒棒的两端可以涂色。现在已知所有的线段要么有一端涂色,要么两端都没有涂色,现在要求把所有的没涂色的部分涂色,使得我们可以把涂色后的棒棒分为N/K组,每组的涂色情况相同。

思路:把没有颜色的棒子,看成一端涂色为0,那么现在每个线段都有一端涂色。我们按照数量来排序,然后每次用最多的去匹配最少的。如果不能匹配,输出“No”。最后把有颜色0的换成1即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define mp make_pair
#define pii pair<int,int>
#define F first
#define S second
using namespace std;
const int maxn=1001;
short int pos[maxn][maxn],a[maxn],b[maxn],num[maxn];
set<pii>S;
int main()
{
    int N,K,M;
    scanf("%d%d",&N,&K); M=N/K;
    rep(i,1,N) {
        scanf("%d",&a[i]);
        if(a[i]==-1) a[i]=0;
        pos[a[i]][++num[a[i]]]=i;
    }
    rep(i,0,N) if(num[i]) S.insert(mp(num[i],i));
    while(!S.empty()){
        pii L=*S.begin();
        pii R=*(--S.end());
        S.erase(L); S.erase(R);
        if(L.F+R.F<M) return puts("No"),0;
        rep(i,1,min(L.F,M)) b[pos[L.S][num[L.S]--]]=R.S;
        rep(i,1,M-min(L.F,M)) b[pos[R.S][num[R.S]--]]=L.S;
        if(num[L.S]) S.insert(mp(num[L.S],L.S));
        if(num[R.S]) S.insert(mp(num[R.S],R.S));
    }
    puts("Yes");
    rep(i,1,N) printf("%d %d\n",a[i]?a[i]:1,b[i]?b[i]:1);
    return 0;
}

猜你喜欢

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