1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1399 Solved: 594
[ Submit][ Status][ Discuss]
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左上角为(x1,y1),右下角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
Sample Input
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
CDQ分治。。
对时间二分,每次执行前半段时间的操作,加给后半段询问
对于询问将它拆为四个点,每个点都维护从左上角到该点的和
加的话用扫描线+树状数组就是了
(花了苟蒻一下午。。。。)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 4E5 + 20;
const int maxm = 2E6 + 20;
struct Q{
int x,y,c,typ,pos;
bool operator < (const Q &b) const {
if (x < b.x) return 1;
if (x > b.x) return 0;
return typ < b.typ;
}
}src[maxn],t[maxn];
int c[maxm],n,m,s;
void CDQ(int l,int r)
{
if (l == r) return;
int mid = (l+r) >> 1;
CDQ(l,mid);
int cur = 0;
for (int i = l; i <= mid; i++)
if (src[i].typ == 1)
t[++cur] = src[i];
for (int i = mid+1; i <= r; i++)
if (src[i].typ == 2)
t[++cur] = src[i],t[cur].pos = i;
sort(t+1,t+cur+1);
for (int i = 1; i <= cur; i++) {
if (t[i].typ == 1) {
for (int j = t[i].y; j <= m; j += j&-j)
c[j] += t[i].c;
}
else {
for (int j = t[i].y; j > 0; j -= j&-j)
src[t[i].pos].c += c[j];
}
}
for (int i = 1; i <= cur; i++)
if (t[i].typ == 1)
for (int j = t[i].y; j <= m; j += j&-j)
c[j] -= t[i].c;
CDQ(mid+1,r);
}
int main()
{
#ifdef YZY
freopen("yzy.txt","r",stdin);
#endif
cin >> s >> m;
int cnt = 0;
for (;;) {
int X1,X2,Y1,Y2,typ;
scanf("%d",&typ);
if (typ == 3) break;
if (typ == 1) {
++cnt;
src[cnt].typ = 1;
scanf("%d%d%d",&src[cnt].x,&src[cnt].y,&src[cnt].c);
}
else {
scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
++cnt;
src[cnt].typ = 2; src[cnt].c = s*(X2-X1+1)*(Y2-Y1+1);
src[cnt].x = X2; src[cnt].y = Y2;
++cnt;
src[cnt].typ = 2;
src[cnt].x = X2; src[cnt].y = Y1 - 1;
++cnt;
src[cnt].typ = 2;
src[cnt].x = X1 - 1; src[cnt].y = Y2;
++cnt;
src[cnt].typ = 2;
src[cnt].x = X1 - 1; src[cnt].y = Y1 - 1;
}
}
CDQ(1,cnt);
for (int i = 1; i <= cnt; i++)
if (src[i].typ == 2) {
int ans = 0;
ans += src[i++].c;
ans -= src[i++].c;
ans -= src[i++].c;
ans += src[i].c;
printf("%d\n",ans);
}
return 0;
}