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; }
It is your time to fight!