小鸟往四个方向飞都枚举一下,数据范围没给,离散以后按在其中一个轴线排序,在线段树上更新墙的id,然后就是点查询在在哪个墙上了。
这题有个trick,因为数据范围没给我老以为是inf设置小了,WA了很多发。(距离可能比0x3f3f3f3f大
实现上,我是把鸟和墙的坐标放一起的,用下标来区别两者。
/********************************************************* * ------------------ * * author AbyssalFish * **********************************************************/ #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> #include<vector> #include<stack> #include<vector> #include<map> #include<set> #include<algorithm> #include<cmath> #include<numeric> #include<cassert> using namespace std;typedef long long ll; const int MAX_N = 5e4+5; int N, M; int dist[MAX_N]; int fly_to[MAX_N]; int wall_cnt[MAX_N];const int MAX_SIZE = MAX_N*3; int x[MAX_SIZE], y[MAX_SIZE]; int rx[MAX_SIZE], ry[MAX_SIZE]; int xs[MAX_SIZE], ys[MAX_SIZE];//discrete data int mpx[MAX_SIZE], mpy[MAX_SIZE];//用于离散idx访问原值 int sp, dat_sz;int *fi;//, *se; bool cmp(int a, int b) {return fi[a] < fi[b];// || (fi[a] == fi[b] && se[a] < se[b]); }/* parameter : 原始数据dat , 名次r ,size, 离散数据 a */void compress(int *dat, int *r, int sz, int *a, int *mp)//int *dat_ {for(int i = 0; i < sz; i++){r[i] = i;}fi = dat; //se = dat_;sort(r,r+sz,cmp);mp[a[r[0]] = 1] = dat[r[0]];for(int i = 1; i < sz; i++){int k = r[i], p = r[i-1];if(dat[k] != dat[p]){mp[ a[k] = a[p]+1 ] = dat[k];}else {a[k] = a[p];}} }void init() {// wall [0 N*2), bird [N*2, Ui)sp = N*2; dat_sz = sp+M;for(int i = 0; i < dat_sz; i++){scanf("%d%d", x+i, y+i);}compress(x, rx, dat_sz, xs, mpx);compress(y, ry, dat_sz, ys, mpy); }#define para int o = 1, int l = 1,int r = n0 #define Tvar int mid = (l+r)>>1, lc = (o<<1), rc = (o<<1|1); #define lsn lc, l, mid #define rsn rc, mid+1, r #define insd ql<=l&&r<=qr const int ST_SIZE = 1<<19;int cv[ST_SIZE]; //完整覆盖,wall的idx , 不完整覆盖 -1, 完全无覆盖 0 int n0; int qpos;int query(para) {if(~cv[o]) return cv[o];else {Tvarreturn qpos <= mid? query(lsn) : query(rsn);} }int ql, qr, qval;void update(para) {if(insd){cv[o] = qval;}else {Tvarif(~cv[o]) {cv[lc] = cv[rc] = cv[o];cv[o] = -1;}if(ql <= mid) update(lsn);if(qr > mid) update(rsn);} }void sweep_line(int k, int *ys, int *xs, int *mpy) {if(k < sp){int k2 = k^1;//trick 小鸟可能在墙的延迟线上,害得我WA了无数发 T_Tif((xs[k2] >= xs[k])){qval = (k>>1)+1;ql = xs[k]; qr = xs[k2];update();}}else {qpos = xs[k];int w_id = query();//assert(w_id != -1);if(w_id) {w_id--;int pos_b = mpy[ys[k]];int d = min( abs(pos_b - mpy[ys[w_id<<1]]), abs(pos_b - mpy[ys[w_id<<1|1]]) );k -= sp;if(d < dist[k]){dist[k] = d; fly_to[k] = w_id;}}} }void fly(int *ry, int *ys, int *xs, int *mpy, int mxx) {n0 = mxx;ql = 1; qr = n0; qval = 0;update();for(int i = 0; i < dat_sz; i++){sweep_line(ry[i],ys,xs,mpy);}ql = 1; qr = n0; qval = 0;update();for(int i = dat_sz-1; i >= 0; i--){sweep_line(ry[i],ys,xs,mpy);} }void solve() {//memset(ans,0x3f,sizeof(ll)*M);fill(dist, dist+M, 0x7fffffff);fly(ry,ys,xs,mpy,xs[rx[dat_sz-1]]);fly(rx,xs,ys,mpx,ys[ry[dat_sz-1]]);memset(wall_cnt,0,sizeof(int)*N);for(int i = 0; i < M; i++) wall_cnt[fly_to[i]]++;for(int i = 0; i < N; i++){printf("%d\n", wall_cnt[i]);} }//#define LOCAL int main() { #ifdef LOCALfreopen("in.txt","r",stdin); #endif//cout<<((int)ceil(log2(15e4))+1);while(~scanf("%d%d", &N, &M)){//assert(N<=MAX_N && M <= MAX_N); init();solve();}return 0; }