HDU 1892 See you~ 解题报告(线段树版)
A了一晚上。。。
题目看起来就是个线段树,不过是平面的。仍然是二分的思想,我们可以每次横向分,纵向分,即4分。二维线段树吧
贴代码:
#include <iostream> using namespace std; #define rect 0,1000,0,1000,1,1 #define defhm int hm=(l+r)>>1; #define defvm int vm=(t+b)>>1; #define ltson l,hm,t,vm,pos<<1,posy<<1 #define rtson hm+1,r,t,vm,pos<<1|1,posy<<1 #define lbson l,hm,vm+1,b,pos<<1,posy<<1|1 #define rbson hm+1,r,vm+1,b,pos<<1|1,posy<<1|1 int old; bool overflow; const int maxn=1111; int sum[maxn<<2][maxn<<2]; void updateFather(int pos,int posy) { sum[pos][posy]=sum[pos<<1][posy<<1]+sum[pos<<1|1][posy<<1]+sum[pos<<1][posy<<1|1]+sum[pos<<1|1][posy<<1|1]; } void build(int l,int r,int t,int b,int pos,int posy) { if(l==r && t==b) { sum[pos][posy]=1; return; } defvm; defhm; if(l<r && t<b) { build(ltson); build(rtson); build(lbson); build(rbson); } else if(l<r && t==b) { build(ltson); build(rtson); } else if(t<b && l==r) { build(ltson); build(lbson); } updateFather(pos,posy); } void update(int px,int py,int add,int l,int r,int t,int b,int pos,int posy) { if(l==r && t==b) { old=sum[pos][posy]; sum[pos][posy]+=add; if(sum[pos][posy]<0) { overflow=true; sum[pos][posy]=0; } return; } defhm; defvm; if(px<=hm && py<=vm) update(px,py,add,ltson); if(px<=hm && vm<py) update(px,py,add,lbson); if(hm<px && py<=vm) update(px,py,add,rtson); if(hm<px && vm<py) update(px,py,add,rbson); updateFather(pos,posy); } int query(int L,int R,int T,int B,int l,int r,int t,int b,int pos,int posy) { if(L<=l&&r<=R&&T<=t&&b<=B) { return sum[pos][posy]; } defhm; defvm; int SUM=0; if(L<=hm && T<=vm) SUM+=query(L,R,T,B,ltson); if(L<=hm && vm<B) SUM+=query(L,R,T,B,lbson); if(hm<R && T<=vm) SUM+=query(L,R,T,B,rtson); if(hm<R && vm<B) SUM+=query(L,R,T,B,rbson); return SUM; } int main() { int T,cas,n; char str[10]; int x1,x2,y1,y2,add; scanf("%d",&cas); for(T=1;T<=cas;T++) { printf("Case %d:\n",T); build(rect); scanf("%d",&n); while(n--) { scanf("%s",str); if(str[0]=='A' || str[0]=='D') { scanf("%d%d%d",&x1,&y1,&add); update(x1,y1,add*(str[0]=='A'?1:-1),rect); } else if(str[0]=='M') { overflow=false; scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&add); update(x1,y1,-add,rect); if(overflow) add=old; update(x2,y2,add,rect); } else { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1>x2) swap(x1,x2); if(y1>y2) swap(y1,y2); printf("%d\n",query(x1,x2,y1,y2,rect)); } } } }
最后要注意的一点是,查询时的两点坐标不一定是升序的,如果x1大于x2,就要交换过来。。。这个坑了我很久。。。