[Educational Codeforces Round 17 E (762E)] Radio stations

题意

给出n个点,每个点有三围(x,r,f)
两个点是冲突的,当 |xixj|min(ri,rj)|fifj|k .
k 给出。
n105,0k10

题解

想法一:
x 从大到小枚举点,每次在kdtree中询问xjxi+rixjrjxi|fjfi|k的点的个数加入答案,再将 (xi,xiri,fi) 插入KDtree里。

觉得想法一要写起来好长,再想想

想法二:
k 最大就10,对每一个f值建二维线段树,然后查询?

还是好长

想法三:
CDQ啊!。。忘了怎么写了,感觉也不短

想法四:
对每一个 f x离散化,并建BIT,存储差分数据,来表示线段 (xiri,xi+ri) 的覆盖( xiri 的地方插入1, xi+ri+1 的地方插入-1)
对所有点按照 xi 从大到小枚举,对 fik fi+k 的BIT询问 xi 位置覆盖了几条线段,加入答案中。
同时将 xiri 记录下来,每次询问之前将 xjrj<xi 的点都在相应的BIT中删去,这样就能保证每次询问合法了。

代码

/// by ztx
/// blog.csdn.net/hzoi_ztx

#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v)  for(i=v.begin();i!=v.end();i++)
#define each(v)    v.begin(),v.end()
#define r(x)   read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}

#define  maxn  100010LL
#define  maxf  10001LL

struct DATA {
    int x, r, f;
    bool operator < (const DATA&B) const { return x < B.x; }
} a[maxn];

struct BIT {
    int sum, n, *C;
    BIT(int n) {
        this->n = n, sum= 0; C = new int[n+1]();
    }
    inline int get(int p) {
        int ret = 0; for (; p; p -= (p&(-p))) ret += C[p]; return ret;
    }
    inline void inc(int p,int x) {
        sum += x; for (; p <= n; p += (p&(-p))) C[p] += x;
    }
} *B[maxf];

std::vector<int>F[maxf];
std::multiset<DATA> S;

inline void insert(int i,int x) {
    int p = lower_bound(each(F[a[i].f]), a[i].x)-F[a[i].f].begin()+1;
    B[a[i].f]->inc(p, x);
}

int main() {
    int n, K, i, j, fl, fr;
    ll ans;
    r(n), r(K);
    Rep (i,1,n) {
        r(a[i].x), r(a[i].r), r(a[i].f);
        F[a[i].f].push_back(a[i].x);
    }
    Rep (i,1,10000) {
        std::sort(each(F[i]));
        B[i] = new BIT(F[i].size());
    }
    std::sort(a+1, a+n+1);
    ans = 0;
    Rep (i,1,n) {
        while (!S.empty() && S.begin()->x<a[i].x)
            insert(S.begin()->r,-1), S.erase(S.begin());
        fl = std::max(1,a[i].f-K), fr = std::min(10000,a[i].f+K);
        Rep (j,fl,fr)
            ans += B[j]->sum - B[j]->get(lower_bound(each(F[j]),a[i].x-a[i].r)-F[j].begin());
        insert(i,1);
        S.insert((DATA){a[i].x+a[i].r,i,0});
    }
    printf("%lld\n", ans);
    END: getchar(), getchar();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值