题意:平面图上有n(2<=n<=10^5)个点,每个点能覆盖住Manhattan距离为w范围内的点,如果一个点被覆盖的次数超过k次那么这个点就是能被删除的,
问那些点能被删除。
题解:对于一个点能覆盖住的是一个以它为中心的菱形,将坐标轴逆时针旋转45度后每个点的覆盖关系不变,维护上下两条线的加减关系,Bit实现即可。
Sure原创,转载请注明出处
#include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> using namespace std; const int maxn = 100002; struct node { int xl,xr; long long y; int kind,id; bool operator < (const node &other) const { if(y == other.y) { return kind > other.kind; } return y < other.y; } }line[maxn * 3]; int xx[maxn * 3],c[maxn * 3],ans[maxn],res[maxn]; int m,n,top,tot; void add(int x1,int x2,long long yy,int kk,int ii) { line[tot].xl = x1; line[tot].xr = x2; line[tot].y = yy; line[tot].kind = kk; line[tot].id = ii; tot++; return; } void read() { memset(c,0,sizeof(c)); top = tot = 0; int x,y,w; for(int i=0;i<n;i++) { scanf("%d %d %d",&x,&y,&w); add(x-y,x-y,(long long)x+y,0,i); add(x-y-w,x-y+w,(long long)x+y-w,1,-1); add(x-y-w,x-y+w,(long long)x+y+w,-1,-1); xx[top++] = x-y; xx[top++] = x-y-w; xx[top++] = x-y+w; } return; } void make() { sort(line , line + tot); sort(xx , xx + top); top = unique(xx , xx + top) - xx; return; } int lowbit(int x) { return x & (-x); } void update(int i,int val) { while(i <= top) { c[i] += val; i += lowbit(i); } return; } int sum(int i) { int res = 0; while(i > 0) { res += c[i]; i -= lowbit(i); } return res; } void solve() { for(int i=0;i<tot;i++) { int l = lower_bound(xx , xx + top , line[i].xl) - xx; int r = lower_bound(xx , xx + top , line[i].xr) - xx; if(l == r) { ans[line[i].id] = sum(l+1); } else { int val = line[i].kind; update(r+2,-val); update(l+1,val); } } top = 0; for(int i=0;i<n;i++) { if(ans[i] > m) { res[top++] = i+1; } } printf("%d\n",top); for(int i=0;i<top;i++) { if(i) printf(" "); printf("%d",res[i]); } if(top) puts(""); return; } int main() { while(~scanf("%d %d",&n,&m)) { read(); make(); solve(); } return 0; }