SGU 394 Berhatton Bit 維護 Manhattan 距離

題意:平面圖上有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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章