题目链接:https://nanti.jisuanke.com/t/41298
题解:先把每个点的val计算出来,剩下的就是CDQ分治+树状数组模板了,
和园丁的烦恼一样了
开始是用的递归求的val
ll f(ll c,ll x,ll y){
if(x==c) return (c-y)+1;
if(y==1) return (c-1)+(c-x)+1;
if(x==1) return (c-1)*2+y;
if(y==c) return (c-1)*3+x;
return 4LL*(c-1)+f(c-2,x-1,y-1);
}
果断超时
然后看了鲲鲲的博客,才知道可以O(1)推出来。
还是菜啊
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 30;
struct node{
int x, y, z, id, op;
ll val;
}q[maxn * 5], tmp[maxn * 5];
ll ans[maxn * 5], sum[maxn * 5];
bool cmp(node x, node y){
if(x.x != y.x) return x.x < y.x;
else if(x.y != y.y) return x.y < y.y;
return x.z < y.z;
}
int lowbit(int x){
return x & (-x);
}
void add(int x, ll val){
if(x == 0) return;
while(x < maxn) {
sum[x]+=val;
x += lowbit(x);
}
}
void del(int x) {
if(x == 0) return;
while(x < maxn) {
sum[x] = 0;
x += lowbit(x);
}
}
ll query(int x){
ll ans = 0;
while(x) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
void CDQ(int l, int r){
if(r - l <= 1) {
return;
}
int mid = l + r >> 1;
CDQ(l, mid);
CDQ(mid, r);
int t1 = l, t2 = mid, cnt = 0;
while(t1 < mid && t2 < r){
if(q[t1].y <= q[t2].y){
if(q[t1].op == 1) add(q[t1].z, q[t1].val);
tmp[cnt++] = q[t1++];
}
else {
if(q[t2].op == 2) ans[q[t2].id] += query(q[t2].z);
else if(q[t2].op == 3) ans[q[t2].id] -= query(q[t2].z);
tmp[cnt++] = q[t2++];
}
}
while(t1 < mid) tmp[cnt++] = q[t1++];
while(t2 < r){
if(q[t2].op == 2) ans[q[t2].id] += query(q[t2].z);
else if(q[t2].op == 3) ans[q[t2].id] -= query(q[t2].z);
tmp[cnt++] = q[t2++];
}
for(int i = 0; i < cnt; i++) {
q[i + l] = tmp[i];
del(tmp[i].z);
}
}
ll f(ll n, ll x, ll y) {
ll p = 0;
ll ans = 0;
if(x <= y && x + y <= n + 1) {
p = x;
ans = y - p + 1;
} else if(x <= y && x + y >= n + 1) {
p = n - y + 1;
ans = n - 3 * p + x + 2;
}else if(x >= y && x + y >= n + 1) {
p = n - x + 1;
ans = 3 * n - 5 * p - y + 4;
} else {
p = y;
ans = 4 * n - 7 * p - x + 5;
}
ans += 4 * (p - 1) * (n - p + 1);
return ans;
}
int main()
{
int T, n, m, qq;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &m, &qq);
for(int i = 0; i < m; i++) {
ll x, y;
scanf("%lld%lld", &x, &y);
ll temp = f(n, n - x + 1, n - y + 1), res = 0;
while(temp) {
res += temp % 10;
temp /= 10;
}
q[i].op = 1;
q[i].val = res;
q[i].x = i;
q[i].y = x + 1;
q[i].z = y + 1;
}
int tot = m;
for(int i = 0; i <= qq; i++) ans[i] = 0;
for(int i = 1; i <= qq; i++) {
int x, y, z, zz;
scanf("%d%d%d%d", &x, &y, &z, &zz);
x++; y++; z++; zz++;
q[tot].id = i; q[tot].op = 2; q[tot].x = tot; q[tot].y = x - 1; q[tot].z = y - 1; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 2; q[tot].x = tot; q[tot].y = z; q[tot].z = zz; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 3; q[tot].x = tot; q[tot].y = x - 1; q[tot].z = zz; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 3; q[tot].x = tot; q[tot].y = z; q[tot].z = y - 1; q[tot].val = 1; tot++;
}
CDQ(0, tot);
for(int i = 1; i <= qq; i++) {
printf("%lld\n", ans[i]);
}
}
return 0;
}