LG7881 [Ynoi2006] rmpq【分块,分治】

这是一道交互题

维护 \(10^9\times 10^9\) 的二维数组,元素属于含幺半群 \(D\),初始时均为单位元 \(e\)\(n\) 次操作:

  • 给定一条水平或竖直的直线将数组分成两部分,再给定 \(d_1,d_2\in D\),两部分分别右乘 \(d_1,d_2\)
  • 单点查询。

\(n\le 10^5\)\(D\) 上的乘法只能进行 \(2\cdot 10^7\) 次。


因为乘法没有交换律,所以只能按照时间顺序依次处理,又因为强制在线,所以考虑按时间分块(根号重构),对每 \(B\) 次修改计算出 \(B^2\) 个区域的值,查询的时候定位到区域的值然后乘起来即可。

现在考虑怎么计算,暴力做法是 \(O(B^3)\) 的,但是若修改都在查询前就可以分治做到 \(O(B^2)\),然后用二进制分组替代这个分治就可以同时修改和查询。空间复杂度 \(O(nB)\),时间复杂度 \(O(nB+n^2/B)\)

#include<bits/stdc++.h>
#define PB emplace_back
using namespace std;
const int N = 256, INF = 1.5e9;
struct Data {
    unsigned short a, b, c, d;
    void operator *= (const Data &x);
    void clr();
};
Data operator * (Data a, const Data &b){a *= b; return a;}
struct Node {
    int n1, n2, *v1, *v2;
    Data *val;
    int siz(){return max(0, n1 + n2 - 2);}
    void init(int _1, int _2){
        v1 = new int [n1 = _1];
        v2 = new int [n2 = _2];
        val = new Data [n1 * n2];
    }
    void init(int x, int op, const Data &d1, const Data &d2){
        if(op){init(1, 2); v2[0] = x; v1[0] = v2[1] = INF;}
        else {init(2, 1); v1[0] = x; v1[1] = v2[0] = INF;}
        val[0] = d1; val[1] = d2;
    }
    Node operator + (const Node &o) const {
        static int p1[N], p2[N], q1[N], q2[N];
        Node res; res.init(n1 + o.n1 - 1, n2 + o.n2 - 1);
        for(int i = 0, j = 0;i < n1;++ i){
            while(j < o.n1 && o.v1[j] < v1[i]){
                p1[i+j] = i; p2[i+j] = j; res.v1[i+j] = o.v1[j]; ++ j;
            }
            p1[i+j] = i; p2[i+j] = j; res.v1[i+j] = v1[i];
        }
        for(int i = 0, j = 0;i < n2;++ i){
            while(j < o.n2 && o.v2[j] < v2[i]){
                q1[i+j] = i; q2[i+j] = j; res.v2[i+j] = o.v2[j]; ++ j;
            }
            q1[i+j] = i; q2[i+j] = j; res.v2[i+j] = v2[i];
        }
        for(int i = 0;i < res.n1;++ i)
            for(int j = 0;j < res.n2;++ j)
                res.val[i*res.n2+j] = val[p1[i]*n2+q1[j]] * o.val[p2[i]*o.n2+q2[j]];
        return res;
    }
    Data qry(int x, int y){
        return val[(upper_bound(v1, v1+n1, x) - v1) * n2 + (upper_bound(v2, v2+n2, y) - v2)];
    }
} st[512];
int tp;
void update(int x, int dim, Data d1, Data d2){
    st[++tp].init(x, dim, d1, d2);
    while(tp > 1 && st[tp-1].siz() <= st[tp].siz() && st[tp].siz() < N)
        st[tp-1] = st[tp-1] + st[tp], -- tp;
}
Data query(int x, int y){
    Data res; res.clr();
    for(int i = 1;i <= tp;++ i) res *= st[i].qry(x, y);
    return res;
}
原文地址:https://www.cnblogs.com/AThousandMoons/p/15696915.html