小鸟往四个方向飞都枚举一下,数据范围没给,离散以后按在其中一个轴线排序,在线段树上更新墙的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 { Tvar return qpos <= mid? query(lsn) : query(rsn); } } int ql, qr, qval; void update(para) { if(insd){ cv[o] = qval; } else { Tvar if(~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_T if((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 ", wall_cnt[i]); } } //#define LOCAL int main() { #ifdef LOCAL freopen("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; }