• 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
    ", ans[i]); 
        return 0;
    }
    View Code
  • 相关阅读:
    【Source教程】Crowbar下载部署与使用方法
    【Source教程】VTFEdit下载安装与使用方法
    【Source教程】GCFScape下载安装与使用
    【Source教程】文章目录
    【资源导航】我所用到过的工具及下载地址
    C# MVC LayUI实现下拉框二级联动
    ASP.NET MVC+Echarts绘制统计图表
    ArcMap操作随记(9)
    ArcMap操作随记(8)
    ArcMap操作随记(7)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7435207.html
Copyright © 2020-2023  润新知