bzoj2989

Posted 123456

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2989相关的知识,希望对你有一定的参考价值。

坐标轴转化+cdq分治

我们发现那个绝对值不太好搞,于是我们把曼哈顿距离转为欧几里得距离,x‘=x-y,y‘=x+y,这样两点之间距离就是max(|x1‘-x2‘|,|y1‘-y2‘|),这个距离要小于等于k,那么就是求转化后坐标系中在以x‘,y‘为中心,边长为2k的正方形中的点数,每次修改就相当于加入一个点,计算平面点数就是cdq分治,按时间排序,对x分治,y插入树状数组,然后就做好了

技术分享
#include<bits/stdc++.h>
using namespace std;
const int N = 400010, base = 200010;
struct query {
    int x, y, opt, minus, id;
    query(int x = 0, int y = 0, int opt = 0, int minus = 0, int id = 0) : x(x), y(y), opt(opt), minus(minus), id(id) {}
    bool friend operator < (query A, query B) {
        return A.x == B.x ? A.id < B.id : A.x < B.x;
    }
} q[N << 1];
vector<query> c;
int n, Q, cnt, tot, m;
int ans[N], a[N], tree[N << 1];
void update(int x, int d) { for(; x <= m; x += x & (-x)) tree[x] += d; }
int ask(int x) { int ret = 0; for(; x; x -= x & (-x)) ret += tree[x]; return ret; }
void cdq(int l, int r)
{
    if(l >= r) return;
    int mid = (l + r) >> 1;
    cdq(l, mid); cdq(mid + 1, r);
    c.clear();
    for(int i = l; i <= mid; ++i) if(q[i].opt == 1) c.push_back(q[i]);
    for(int i = mid + 1; i <= r; ++i) if(q[i].opt == 2) c.push_back(q[i]);
    sort(c.begin(), c.end());
    for(int i = 0; i < c.size(); ++i)
    {
        query o = c[i];
        if(o.opt == 1) update(o.y, 1);
        else ans[o.id] += ask(o.y) * o.minus;
    }
    for(int i = 0; i < c.size(); ++i) if(c[i].opt == 1) update(c[i].y, -1);
}
int main()
{
    scanf("%d%d", &n, &Q);
    for(int i = 1; i <= n; ++i) 
    {
        scanf("%d", &a[i]);
        q[++cnt] = query(i - a[i], i + a[i] + base, 1, 0, 0);
        m = max(m, i + a[i] + base);
    }
    for(int i = 1; i <= Q; ++i)
    {
        char s[10];
        int x, y, k;
        scanf("%s", s);
        if(s[0] == M) 
        {
            scanf("%d%d", &x, &y);
            q[++cnt] = query(x - y, x + y + base, 1, 0, 0), a[x] = y;
            m = max(m, x + y + base);
        }       
        if(s[0] == Q) 
        {
            scanf("%d%d", &x, &k);
            ++tot;
            m = max(m, x + a[x] + k + base);
            q[++cnt] = query(x - a[x] + k, x + a[x] + k + base, 2, 1, tot); 
            q[++cnt] = query(x - a[x] - k - 1, x + a[x] - k - 1 + base, 2, 1, tot);
            q[++cnt] = query(x - a[x] - k - 1, x + a[x] + k + base, 2, -1, tot);
            q[++cnt] = query(x - a[x] + k, x + a[x] - k - 1 + base, 2, -1, tot);    
        }
    }
    cdq(1, cnt);
    for(int i = 1; i <= tot; ++i) printf("%d\n", ans[i]); 
    return 0;
}
View Code

 

以上是关于bzoj2989的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2989数列 KD-tree

bzoj2989&&4170数列——二进制分组+主席树

「日常训练」All Friends(POJ-2989)

bzoj1076: [SCOI2008]奖励关(期望dp+状压dp)

codevs 2989 寻找somebody

noi 2989 糖果