HDU 5454 Excited Database 線段樹的維護
阿新 • • 發佈:2018-12-24
Excited Database
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 129 Accepted Submission(s): 26
She says that any excited database can answer the queries efficiently.
You are given the two dimensional database as a matrix A
Then q operations or queries will be given in turn.
You should maintain the database for two type of operations:
⋅1LR: for each element A[i][j] which satisfy L≤i+j≤R, increase the value to A[i][j]+1, where 2≤L≤R≤2n.
⋅2LR: for each element A
Meanwhile, you should answer the queries:
⋅3x1x2y1y2: count the value of elements A[i][j] which satisfy x1≤i≤x2 and y1≤j≤y2, where 1≤x1<x2≤n and 1≤y1<y2≤n.
Input The input contains several test cases. The first line of the input is a single integert
Each test case contains several lines. The first line contains the integer n and q.
The i-th line of the next q lines contains an operation ‘‘1LR" or ‘‘2LR", or a query ‘‘3x1x2y1y2".
The sum of n for all test cases would not be larger than 200000 and the sum of q would not be larger than 50000. Output For each test case, you should output answers to queries printed one per line. Sample Input 2 6 6 2 0 1 3 1 4 3 5 3 2 5 2 3 1 5 7 3 1 4 3 5 3 2 5 2 3 6 26 2 -4 -1 3 1 4 2 5 3 3 6 4 6 1 4 7 3 2 5 2 3 3 1 4 2 5 2 -3 -1 3 1 4 3 5 1 3 5 1 2 3 3 2 5 2 3 3 1 4 2 5 3 3 6 4 6 2 0 4 3 1 4 3 5 3 1 4 2 5 1 9 11 2 1 2 3 2 5 2 3 3 3 6 4 6 2 -2 2 1 7 12 3 1 4 3 5 3 2 5 2 3 3 1 4 2 5 3 3 6 4 6 Sample Output Case #1: 3 4 11 10 Case #2: 10 6 8 22 26 12 38 13 32 44 23 30 49 33 67 53 Source 題意:在一個n*n的矩陣中,(n<=20w),有兩種操作:操作1:將A[i]j](L<= i + j <=R) +1,操作2:將A[i][j](L<=i - j < =R ) +1. 詢問x1,y1到x2,y2區域內的和。 思路:按照主對角線和副對角線分別建立線段樹,操作就是區間累加操作,維護需要維護區間的sum和A[i]*i的和,查詢是將矩形分解為2個等腰直角三角形和一個平行四邊形。分別進行詢問。 程式碼:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef __int64 LL;
const int maxn = 300005;
struct tree
{
LL suml[maxn << 2], sumr[maxn << 2], sum[maxn << 2];
LL add[maxn << 2];
inline void pushup(int id, int L, int R)
{
LL mid = L + R >> 1;
sum[id] = sum[id << 1] + sum[id << 1 | 1];
suml[id] = suml[id << 1] + (mid - L + 1)*sum[id << 1 | 1] + suml[id << 1 | 1];
sumr[id] = sumr[id << 1 | 1] + sumr[id << 1] + (R - mid)*sum[id << 1];
}
inline void pushdown(int id, int L, int R)
{
int mid = L + R >> 1;
if (add[id])
{
LL ln = mid - L + 1;
LL rn = R - mid;
add[id << 1] += add[id];
add[id << 1 | 1] += add[id];
sum[id << 1] += add[id] * ln;
sum[id << 1 | 1] += add[id] * rn;
suml[id << 1] += add[id] * (1 + ln)*ln >> 1;
suml[id << 1 | 1] += add[id] * (1 + rn)*rn >> 1;
sumr[id << 1] += add[id] * (1 + ln)*ln >> 1;
sumr[id << 1 | 1] += add[id] * (1 + rn)*rn >> 1;
add[id] = 0;
}
}
void build()
{
memset(sum, 0, sizeof(sum));
memset(suml, 0, sizeof(suml));
memset(sumr, 0, sizeof(sumr));
memset(add, 0, sizeof(add));
}
LL queL(int id, int L, int R, int l, int r)
{
// if(id>400000) while(1);
if (l <= L&&R <= r) return (L - l)*sum[id] + suml[id];
else
{
pushdown(id, L, R);
int mid = L + R >> 1;
LL res = 0;
if (l <= mid) res += queL(id << 1, L, mid, l, r);
if (mid<r) res += queL(id << 1 | 1, mid + 1, R, l, r);
return res;
}
}
LL queR(int id, int L, int R, int l, int r)
{
if (l <= L&&R <= r) return (r - R)*sum[id] + sumr[id];
else
{
pushdown(id, L, R);
int mid = L + R >> 1;
LL res = 0;
if (l <= mid) res += queR(id << 1, L, mid, l, r);
if (mid<r) res += queR(id << 1 | 1, mid + 1, R, l, r);
return res;
}
}
LL que(int id, int L, int R, int l, int r)
{
if (l <= L&&R <= r) return sum[id];
else
{
pushdown(id, L, R);
int mid = L + R >> 1;
LL res = 0;
if (l <= mid) res += que(id << 1, L, mid, l, r);
if (mid<r) res += que(id << 1 | 1, mid + 1, R, l, r);
return res;
}
}
void op(int id, int L, int R, int l, int r)
{
if (l <= L&&R <= r)
{
LL sn = R - L + 1;
add[id]++;
sum[id] += sn;
suml[id] += (1 + sn)*sn >> 1;
sumr[id] += (1 + sn)*sn >> 1;
}
else
{
pushdown(id, L, R);
int mid = L + R >> 1;
if (l <= mid) op(id << 1, L, mid, l, r);
if (mid<r) op(id << 1 | 1, mid + 1, R, l, r);
pushup(id, L, R);
}
}
}tz, tf;
int main()
{
int T;
scanf("%d", &T);
int ks = 0;
while (T--)
{
printf("Case #%d:\n", ++ks);
tz.build();
tf.build();
int n, m;
scanf("%d %d", &n, &m);
while (m--)
{
int op;
scanf("%d", &op);
if (op == 1)
{
int l, r;
scanf("%d %d", &l, &r);
tf.op(1, 1, n << 1, l, r);
}
else if (op == 2)
{
int l, r;
scanf("%d %d", &l, &r);
l += n;
r += n;
tz.op(1, 1, n << 1, l, r);
}
else
{
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &x2, &y1, &y2);
LL ans = 0;
int A, B, C, D;
A = x1 - y1 + n;
B = x1 - y2 + n;
C = x2 - y2 + n;
D = x2 - y1 + n;
if (D >= max(A, C) + 1) ans += tz.queR(1, 1, n << 1, max(A, C) + 1, D);
if (B <= min(A, C) - 1) ans += tz.queL(1, 1, n << 1, B, min(A, C) - 1);
ans += tz.que(1, 1, n << 1, min(A, C), max(A, C))*(min(y2 - y1, x2 - x1) + 1);
A = x1 + y1;
B = x1 + y2;
C = x2 + y2;
D = x2 + y1;
if (A <= min(B, D) - 1) ans += tf.queL(1, 1, n << 1, A, min(B, D) - 1);
if (C >= max(B, D) + 1) ans += tf.queR(1, 1, n << 1, max(B, D) + 1, C);
ans += tf.que(1, 1, n << 1, min(B, D), max(B, D))*(min(y2 - y1, x2 - x1) + 1);
printf("%I64d\n", ans);
}
}
}
return 0;
}