树状数组一般的操作只有:
1.单点更新,区间查询
2.区间更新,单点查询
其中区间更新和单点更新不能同时写在一起,会对树状数组的结构早成影响。
这题:WA的情况主要是没有考虑到(x1,y1)可能大于(x2,y2);
训练:训练题链接
代码:
#include<iostream> #include<vector> #include<string> #include<queue> #include<map> #include<cstdio> #include<cstring> #define maxn 2005 #define INF 0xfffffff #define N 1005 #define min(a,b) a<b?a:b #define max(a,b) a>b?a:b using namespace std; int c[maxn][maxn]; char s[10]; void swap(int& x,int& y) { int tmp=y; y=x; x=tmp; } int lowbit(int x) { return x&(-x); } void updata1(int x,int y,int num)//单点更新 { for(int i=x; i<=N; i+=lowbit((i))) { for(int j=y; j<=N; j+=lowbit(j)) { c[i][j]+=num; } } } /* void updata2(int x,int y,int num)//区间更新 { for(int i=x;i>0;i-=lowbit(i)) { for(int j=y;j>0;j-=lowbit(j)) { c[i][j]+=num; } } } */ int sum1(int x,int y)//区间查询 { int ret=0; for(int i=x; i>0; i-=lowbit((i))) { for(int j=y; j>0; j-=lowbit((j))) { ret+=c[i][j]; } } return ret; } /* int sum2(int x,int y)//单点查询 { int ret=0; for(int i=x;i<=N;i+=lowbit(i)) { for(int j=y;j<=N;j+=lowbit(j)) { ret+=c[i][j]; } } return ret; } */ int main() { int t,x1,y1,x2,y2,n,n1; scanf("%d",&t); for(int tt=1; tt<=t; tt++) { printf("Case %d:\n",tt); memset(c,0,sizeof(c)); for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) { updata1(i,j,1); } scanf("%d",&n); while(n--) { scanf("%s",s); if(s[0]=='S') { scanf("%d %d %d %d",&x1,&y1,&x2,&y2); if(x1>x2)//注意下x1和x2的大小,总是大的减去小的 { swap(x1,x2); } if(y1>y2) { swap(y1,y2); } x1++,y1++,x2++,y2++; printf("%d\n",(sum1(x2,y2)-sum1(x2,y1-1)-sum1(x1-1,y2)+sum1(x1-1,y1-1))); } else if(s[0]=='A') { scanf("%d %d %d",&x1,&y1,&n1); x1++,y1++; updata1(x1,y1,n1); } else if(s[0]=='D') { scanf("%d %d %d",&x1,&y1,&n1); x1++,y1++; x2=x1,y2=y1; int tmp=sum1(x2,y2)-sum1(x2,y1-1)-sum1(x1-1,y2)+sum1(x1-1,y1-1); if(tmp<n1) n1=tmp; updata1(x1,y1,-n1);//单点更新 } else { scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&n1); x1++,y1++,x2++,y2++; //单点查询 //cout<<sum2()<<endl; int tmp=sum1(x1,y1)-sum1(x1,y1-1)-sum1(x1-1,y1)+sum1(x1-1,y1-1); if(tmp<n1) n1=tmp; updata1(x1,y1,-n1);//单点更新 updata1(x2,y2,n1);//单点更新 } } } return 0; }