cdq分治论文中的题目,通过cdq分治可以做到降维,然后用树状数组维护就可以了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
const int maxn = 2002000;
LL c[maxn], ans[maxn];
struct query
{
int x, y, type, v, id, q;
query() {}
query(int x, int y, int v, int type, int id, int q)
:x(x), y(y), v(v), type(type), id(id), q(q) {}
bool operator < (const query& rhs) const
{
return x < rhs.x;
}
}Q[maxn];
int W;
int lowbit(int x)
{
return x & (-x);
}
void add(int x, LL ad)
{
while(x <= W)
{
c[x] += ad;
x += lowbit(x);
}
}
LL sum(int x)
{
LL ret = 0;
while(x)
{
ret += c[x];
x -= lowbit(x);
}
return ret;
}
void cdq(int l, int r)
{
if(l == r) return ;
int m = (l + r) >> 1;
cdq(l, m); cdq(m + 1, r);
sort(Q + l, Q + m + 1);
sort(Q + m + 1, Q + r + 1);
int now = l;
for(int i = m + 1; i <= r; i ++)
{
while(now <= m && Q[now].x <= Q[i].x)
{
if(Q[now].type == 1) add(Q[now].y, Q[now].v);
now ++;
}
if(Q[i].type == 2) ans[Q[i].q] += Q[i].v * sum(Q[i].y);
}
for(int i = l; i < now; i ++)
{
if(Q[i].type == 1) add(Q[i].y, -Q[i].v);
}
}
int main()
{
// freopen("mokia.in", "r", stdin);
// freopen("mokia.out", "w", stdout);
int op;
scanf("%d%d", &op, &W);
int tot = 0, qsiz = 1;
while(scanf("%d", &op))
{
if(op == 3) break;
if(op == 1)
{
int x, y, v;
scanf("%d%d%d", &x, &y, &v);
tot ++;
Q[tot] = query(x, y, v, 1, tot, 0);
}
else
{
int x1, x2, y1, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
tot ++;
Q[tot] = query(x1 - 1, y1 - 1, 1, 2, tot, qsiz);
tot ++;
Q[tot] = query(x1 - 1, y2, -1, 2, tot, qsiz);
tot ++;
Q[tot] = query(x2, y1 - 1, -1, 2, tot, qsiz);
tot ++;
Q[tot] = query(x2, y2, 1, 2, tot, qsiz);
qsiz ++;
}
}
CLR(c, 0); CLR(ans, 0);
cdq(1, tot);
for(int i = 1; i < qsiz; i ++)
printf("%I64d\n", ans[i]);
}