https://codeforces.com/gym/100513/problem/B
弱智模拟题,比赛的时候没看懂题意,然后K卡2个半小时,GG
对于一面是i的考虑,如果>=k/n,那么就把中间能成套的全部拿出来,随便选个(i,1)作为同样的颜色,剩下的就是res[i]%(k/n),需要跟别的颜色或者是没染颜色的blanket进行配成一套,那么选个剩下的中最大的配就行了,然后不足的用没染色的即-1来满足。
#include<bits/stdc++.h>
using namespace std;
const int maxl=1010;
int n,k,tot,flag;
int b[maxl],res[maxl];
struct node
{
int x,y;
}ans[maxl];
typedef pair<int,int> p;
set <p> s;
int a[maxl][maxl];
inline void prework()
{
scanf("%d%d",&k,&n);
int x;
for(int i=1;i<=k;i++)
{
scanf("%d",&x);
if(x>0)
a[x][++res[x]]=i;
else
b[++b[0]]=i;
}
for(int i=1;i<=n;i++)
if(res[i]>0)
s.insert(make_pair(res[i],i));
}
inline void mainwork()
{
p dx,dd;int l,r,t,bnum;flag=1;
while(s.begin()!=s.end())
{
dx=(*s.begin());l=dx.second;t=res[l]/(k/n);
for(int i=1;i<=t;i++)
{
for(int j=res[l];j>res[l]-(k/n);j--)
ans[a[l][j]]=node{l,1};
res[l]-=k/n;
}
dd=(*s.rbegin());r=dd.second;
s.erase(s.begin());
if(res[l]==0)
continue;
if(l==r)
{
if(b[0]<(k/n)-res[l])
{
flag=0;
return;
}
for(int j=res[l];j>=1;j--)
ans[a[l][j]]=node{l,1};
for(int j=b[0];j>b[0]-(k/n-res[l]);j--)
ans[b[j]]=node{l,1};
b[0]-=k/n-res[l];res[l]=0;
}
else
{
s.erase(s.find(make_pair(res[r],r)));
for(int j=res[l];j>=1;j--)
ans[a[l][j]]=node{l,r};
bnum=max(0,(k/n-res[l])-res[r]);
for(int j=res[r];j>res[r]-(k/n-res[l]-bnum);j--)
ans[a[r][j]]=node{l,r};
res[r]-=k/n-res[l];
for(int j=b[0];j>b[0]-bnum;j--)
ans[b[j]]=node{l,r};
b[0]-=bnum;
if(res[r]>0)
s.insert(make_pair(res[r],r));
res[l]=0;
}
}
if(b[0]>0)
{
assert(b[0]%(k/n)==0);
for(int j=b[0];j>=1;j--)
ans[b[j]]=node{1,1};
}
}
inline void print()
{
if(flag)
{
puts("Yes");
for(int i=1;i<=k;i++)
printf("%d %d\n",ans[i].x,ans[i].y);
}
else
puts("No");
}
int main()
{
prework();
mainwork();
print();
return 0;
}