/*一失足成千古恨啊~少写了一个等号,调了一个晚上。。。
比赛的时候自动给自己加条件限制啊,自己把题目给想难了,赛后听完思路后恍然大悟,
不过大悟之后,依然发现,代码实现并不简单啊(我是菜鸟。。。。)
首先,每一双鞋最多只能对应两个人选,也就是说,有三种情况
第一种是在一双鞋对应两个人的情况下,这双鞋也同时作为唯一选择对应另一个人,
所以,优先把鞋给唯一对应的人,然后进行相应的分配
第二种是有两个人同时对应了相同的两双鞋
所以,一人对应一双鞋,主要注意分配后的前后选择
第三种是连续的人都对应两双鞋
所以,剔除最小的那双鞋,然后一一对应
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
#define maxn 1000000
#define INF 1000000000
struct in
{
int s,c,num;
}shoes[maxn];
long long sum=0,k=0;//主要sum可能暴int
struct xx
{
int d,l,num;
}people[maxn];
struct yy
{
int a,b;
}final[maxn];
int cmp (in a,in b)
{
return a.s<b.s;
}
int cmp1(xx a,xx b)
{
return a.l<b.l;
}
int one[maxn],two[maxn][2];
bool test1(int l,int r)
{
for(int i=l;i<=r;i++)
{
if(one[i])//如果有一双鞋是唯一对应
{
for(int j=l;j<i;j++)
{
final[k].a=two[j+1][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
final[k].a=one[i];
final[k++].b=shoes[i].num;
sum+=shoes[i].c;
for(int j=i+1;j<=r;j++)
{
final[k].a=two[j][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
return true;
}
}
return false;
}
bool test2(int l,int r)
{
for(int i=l+1;i<=r;i++)
{
if(two[i][0] && two[i][1])//如果有两双鞋被两个人对应
{
for(int j=l;j<i-1;j++)
{
final[k].a=two[j+1][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
final[k].a=two[i][0];
final[k++].b=shoes[i-1].num;
sum+=shoes[i-1].c;
final[k].a=two[i][1];
final[k++].b=shoes[i].num;
sum+=shoes[i].c;
for(int j=i+1;j<=r;j++)
{
final[k].a=two[j][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
return true;
}
}
return false;
}
int main()
{
int n,m;
while(cin>>n)
{
for(int i=0;i<n;i++)
{
scanf("%d%d",&shoes[i].c,&shoes[i].s);
shoes[i].num=i+1;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&people[i].d,&people[i].l);
people[i].num=i+1;
}
sort(shoes,shoes+n,cmp);//从小到大的排序
sort(people,people+m,cmp1);
memset(one,0,sizeof(one));
memset(two,0,sizeof(two));
sum=0,k=0;
int i,j;
for(i=0,j=0;i<n&&j<m;)
{
if(shoes[i].s<people[j].l)
{
i++;
}
else if(shoes[i].s==people[j].l && i+1<n && shoes[i+1].s==people[j].l+1)
{
if(shoes[i].c<=people[j].d && shoes[i+1].c<=people[j].d)
{
if(two[i+1][0]==0)
{
two[i+1][0]=people[j].num;
}
else
{
two[i+1][1]=people[j].num;
}
}
else if(shoes[i].c<=people[j].d)
{
one[i]=people[j].num;
}
else if(shoes[i+1].c<=people[j].d)
{
one[i+1]=people[j].num;
}
j++;
}
else if(shoes[i].s==people[j].l||shoes[i].s==people[j].l+1)
{
if(people[j].d>=shoes[i].c)
{
one[i]=people[j].num;
}
j++;
}
else
j++;
}
i=0;
while(i<n)
{
int l,r;
l=i;
for(r=i+1;r<n && two[r][0];r++);
r--;
i=r+1;
if(l==r)
{
if(one[l])
{
final[k].a=one[l];
final[k++].b=shoes[l].num;
sum+=shoes[l].c;
}
}
else
{
if(!test1(l,r))
{
if(!test2(l,r))
{
int minx=INF+1,id;
for(int j=l;j<=r;j++)
{
if(minx>shoes[j].c)
{
minx=shoes[j].c;//选出最小的,剔除后进行挑选
id=j;
}
}
for(int j=l;j<id;j++)
{
final[k].a=two[j+1][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
for(int j=id+1;j<=r;j++)
{
final[k].a=two[j][0];
final[k++].b=shoes[j].num;
sum+=shoes[j].c;
}
}
}
}
}
cout<<sum<<endl;
cout<<k<<endl;
for(int i=0;i<k;i++)
{
printf("%d %d\n",final[i].a,final[i].b);
}
}
return 0;
}
Codeforces Round #113 (Div. 2) D. Shoe Store
最新推荐文章于 2024-08-11 12:51:39 发布