这是一道交互题
维护 \(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;
}