今天训练赛好萎,多亏有队友。
题意:
敌人有n个需要我方炸毁的目标,已知每个目标的坐标,我方发动了m次爆炸攻击,每次攻击有两个参数:c d,c为0表示炸毁x=d上的所有目标,c为1表示炸毁y=d上的所有目标。问每次炸毁了多少目标。
Input
Multiple test cases and each test cases starts with two non-negative integer N (N<=100,000) and M (M<=100,000) denoting the number of target bases and the number of scheduled bombers respectively. In the following N line, there is a pair of integers x and y separated by single space indicating the coordinate of position of each opponent’s base. The following M lines describe the bombers, each of them contains two integers c and d where c is 0 or 1 and d is an integer with absolute value no more than 10
9, if c = 0, then this bomber will bomb the line x = d, otherwise y = d. The input will end when N = M = 0 and the number of test cases is no more than 50.
Output
For each test case, output M lines, the ith line contains a single integer denoting the number of bases that were destroyed by the corresponding bomber in the input. Output a blank line after each test case.
直接模拟遍历即可,但是一开始算复杂度发现O(n*m)根本破不了,后来想起来动态存储现存点的信息的话每个点只会被遍历一次,这样复杂度就是O(MAX(N,M)),可以实现。所谓动态存储现存点,就是要能快速从某条线的集合里删除一个点,用set实现,logn删除,由于坐标范围很大,先离散化一下。注意数据中存在两个目标在同一个坐标,所以需要用multiset存储线上的信息。
代码如下:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
#define mxn 100010
struct point{
int x,y;
}p[mxn];
int xx[mxn],yy[mxn];
map<int,int> M[2];
multiset<int> S[2][mxn];
multiset<int>::iterator it,ed;
int n,m;
void discrete(){
sort(xx,xx+n);
sort(yy,yy+n);
int cntx=unique(xx,xx+n)-xx;
int cnty=unique(yy,yy+n)-yy;
M[0].clear();
M[1].clear();
for(int i=0;i<cntx;++i) M[0].insert(pair<int,int>(xx[i],i));
for(int i=0;i<cnty;++i) M[1].insert(pair<int,int>(yy[i],i));
for(int i=0;i<n;++i){
p[i].x=M[0][p[i].x];
p[i].y=M[1][p[i].y];
}
for(int i=0;i<cntx;++i) S[0][i].clear();
for(int i=0;i<cnty;++i) S[1][i].clear();
}
void explode(int c,int d){
if(M[c].find(d)==M[c].end()){
puts("0");
return;
}
int coor=M[c][d];
int sz=S[c][coor].size();
printf("%d\n",sz);
ed=S[c][coor].end();
for(it=S[c][coor].begin();it!=ed;++it){
int tem=*it;
S[1-c][tem].erase(coor);
}
S[c][coor].clear();
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF&&n&&m){
for(int i=0;i<n;++i){
scanf("%d%d",&p[i].x,&p[i].y);
xx[i]=p[i].x;
yy[i]=p[i].y;
}
discrete();
for(int i=0;i<n;++i){
S[0][p[i].x].insert(p[i].y);
S[1][p[i].y].insert(p[i].x);
}
int c,d;
for(int q=0;q<m;++q){
scanf("%d%d",&c,&d);
explode(c,d);
}
puts("");
}
return 0;
}