一.题面及大意
题面
大意:
有一张空白的,长为H,宽为W的卡片。现有N个数字要往里填充
ai,bi表示第ai行第bi列的数字为i。
例如:
2,3表示从上往下数第二行,从左往右数第3列有一个数字。
先要进行以下规则删去空白:
1.如果有一行是空白的,那么把这一行删去,并将此行下方的卡片整体向上 平移。
2. 如果有一列是空白的,那么把这一列删去,并将此列右方的卡片整体向左平移。
直到没有一行,或一列为完全空白为止。
输出最后每个数的位置
样例及图示:
样例输入
4 5 2
3 2
2 5
样例输出
2 1
1 2
图示:
以*代表没有数
`*****
****2
*1****
删去后:
*2
1*
``
二.分析
对于每个数而言,它们最后的位置是与自身在原卡片中的坐标排名有关的
即 最左边的卡片最后一定还在最左边,最上边的卡片一定最后还在最上边。
设以y坐标从小到大排完序后每个数分别为a1,a2,a3,a4…
那么 最后a1.y一定等于1,a2一定等于a1.y+1(如果原卡片中a1.y==a2.y 那么最后a2.y=a1.y) 以此类推 我们就可以以O(N)的时间复杂度解决问题。
三.代码实现
#include
using namespace std;
const int N=1e5+10;
int n;
long long h,l;
long long x,y;
struct card{//结构体card 分别记录每张卡片的原x坐标 y坐标 id 及最后的x坐标 y坐标
long long x,y;//原x,y
int id;
long long row,line;//最后的x,y
}f[N];
bool cmp_h(card a,card b){//以x坐标排序
return a.x<b.x;
}
bool cmp_l(card a,card b){//以y坐标排序
return a.y<b.y;
}
bool cmp_id(card a,card b){//以输入顺序排序 最后输出
return a.id<b.id;
}
int main(){
cin>>h>>l>>n;
for(int i=1;i<=n;i++){//输入
cin>>x>>y;
f[i].x=x;
f[i].y=y;
f[i].id=i;
}
sort(f+1,f+n+1,cmp_h);//以x排序 确定每个数最后的x坐标
f[1].row=1;
for(int i=2;i<=n;i++){
if(f[i].x==f[i-1].x) f[i].row=f[i-1].row;//易错!!! 如果在原卡片中x坐标相同 那么最后也一定相同
else f[i].row=f[i-1].row+1;
}
sort(f+1,f+n+1,cmp_l);//以y排序 确定每个数最后的y坐标
f[1].line=1;
for(int i=2;i<=n;i++){//同上
if(f[i].y==f[i-1].y) f[i].line=f[i-1].line;
else f[i].line=f[i-1].line+1;
}
sort(f+1,f+n+1,cmp_id);//以输入顺序排回来
for(int i=1;i<=n;i++){//输出
cout<<f[i].row<<' '<<f[i].line<<endl;
}
return 0;//神来之笔
}