本来是不打算写题解来着,但是它残忍的WA了我好多发
这道题之所以写这么久...是因为研究了好久二维线段树..Orz 还是知道会MLE的情况下(所谓没事找事做),写了个模板,不知道能不能A题...
最后还是用的二维树状数组来着,线段树空间耗费too大了...
题目就是讲,最开始矩阵每个方格都有一本书~ 然后 有如下操作:
A X Y Z 在(x,y)增加z本书
D X Y Z 从(x,y)拿走z本书,如果不够z本,就拿走完。
S X Y N M 为由(x,y)(n,m)组成的矩阵里有多少本书,值得注意的是(x ,y) 不一定在(n,m)的左边,好吧,我在这里坑了
M X Y N M Z 从(x,y)出,拿走z本书到(n,m)处,若不够,则拿走(x,y)处的所有书到(n,m)处...吾在此处也坑了好久...
写这个是要提醒自己...c[x][y]!=a[x][y] 写着写着就写忘了...
code :
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define LL __int64
#define ls v<<1
#define rs v<<1|1
//#define LOCAL
using namespace std;
const int INF=0x3ffffff;
const int MAXN=1100;
int aa[MAXN][MAXN],cc[MAXN][MAXN];
int lowbit(int x){
return x&(-x);
}
void add(int x,int y,int val)
{
while(x<=1001)
{
int yy=y;
while(yy<=1001)
{
cc[x][yy]+=val;
yy+=lowbit(yy);
}
x+=lowbit(x);
}
}
int sum(int x,int y)
{
int rez=0;
while(x)
{
int yy=y;
while(yy)
{
rez+=cc[x][yy];
yy-=lowbit(yy);
}
x-=lowbit(x);
}
return rez;
}
void Init(){
for(int i=0;i<=1002;i++)
for(int j=0;j<=1002;j++)
cc[i][j]=0,aa[i][j]=1;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(false);
int t,a,b,c,d,e,n;
char op[10];
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
Init();
scanf("%d",&n);
printf("Case %d:\n",cas);
for(int i=1;i<=1001;i++)
for(int j=1;j<=1001;j++)
add(i,j,1);
while(n--)
{
scanf("%s",op);
if(op[0]=='S'){
scanf("%d%d%d%d",&a,&b,&c,&d);
int ans=0;
if(a>c) swap(a,c);
if(b>d) swap(b,d);
ans=sum(c+1,d+1)+sum(a,b)-sum(a,d+1)-sum(c+1,b);
printf("%d\n",ans);
}
else if(op[0]=='A'){
scanf("%d%d%d",&a,&b,&c);
aa[a+1][b+1]+=c;
add(a+1,b+1,c);
}
else if(op[0]=='M'){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
if(aa[a+1][b+1]<e) {
e=aa[a+1][b+1];
}
aa[a+1][b+1]-=e;
add(a+1,b+1,-e);
aa[c+1][d+1]+=e;
add(c+1,d+1,e);
}
else if(op[0]=='D'){
scanf("%d%d%d",&a,&b,&c);
if(aa[a+1][b+1]<c) {
c=aa[a+1][b+1];
}
aa[a+1][b+1]-=c;
add(a+1,b+1,-c);
}
}
}
return 0;
}