地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3018
题意:在平面内最多又32768个点,现在有两种操作,1:在一些点上加上一个数n,2:询问一个矩形区域内的点的数的和
分析:这题一看像线段树,想离线搞,发现不好处理,也许可以,不过我是做不来了,后来自己YY了下二维的线段树,从来没写过= =,一开始发现空间会爆,再一想,其实很多节点是没必要增加的,然后就可以做了,大体思路如下:
每个节点保存一个矩形,还有这个矩形区域内的和,这个节点可以分为四个子节点,现在对于插入操作,直接不停的将矩形范围缩小,直到成为一个点,这样每个点最多带来log(n)个节点(n为离散化后x或y的数量),也就是总的节点个数为32768*logn,这样是完全可以的,而查找的话,跟线段树差不多,每次判断当前区域是否覆盖整个节点,是的话就返回这块区域的和,否则就递归与之有覆盖的子矩形。。。好吧,好久没写,表达能力又变差了,具体看代码,感觉练了一阵子的各种树,再写这样的题还是得心应手的^_^
代码:
/** head files*/ #include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <cassert> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> using namespace std; /** some operate*/ #define REP(i,n) for(int i=0;i<(n);++i) #define FOR(i,l,h) for(int i=(l);i<=(h);++i) #define DWN(i,h,l) for(int i=(h);i>=(l);--i) #define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e) #define CLR(arr) memset(arr,0,sizeof(arr)) #define MAX3(a,b,c) max(a,max(b,c)) #define MAX4(a,b,c,d) max(max(a,b),max(c,d)) #define MIN3(a,b,c) min(a,min(b,c)) #define MIN4(a,b,c,d) min(min(a,b),min(c,d)) /** some const*/ #define N 800100 #define PI acos(-1.0) #define oo 1000000000 #define loo 1000000000000000000LL #define eps 1e-8 /** some alias*/ typedef long long LL; int dx[]={0,0,-1,1}; int dy[]={-1,1,0,0}; /** Global variables*/ /** some template names, just push ctrl+j to get it in*/ //getint 读入优化 //manacher 求最长回文子串 //pqueue 优先队列 //combk n元素序列的第m小的组合和 //pmatrix n个点的最大子矩阵 //suffixarray 后缀数组 //sbtree 平衡树 struct retange { int x1,y1,x2,y2; retange(){} retange(int x1, int y1, int x2, int y2):x1(x1),y1(y1),x2(x2),y2(y2){} bool cover(const retange &a)const { if(x1>a.x1||x2<a.x2||y1>a.y1||y2<a.y2)return 0; return 1; } bool interset(const retange &a)const { if(x1>a.x2||y1>a.y2||a.x1>x2||a.y1>y2)return 0; return 1; } bool ok() { return x1>=x2&&y1>=y2; } int mx() { return (x1+x2)>>1; } int my() { return (y1+y2)>>1; } void rd(char *s) { sscanf(s,"%d%d%d%d",&x1,&x2,&y1,&y2); } }; struct Node { retange r; Node *son[4]; LL sum; }TNode,*nil=&TNode; Node mem[N],*C=mem; Node* Create(retange r) { C->r=r; C->sum=0; REP(i,4)C->son[i]=nil; return C++; } void Update(int x, int y, int n, Node *now) { now->sum+=n; while(1) { int mx=now->r.mx(); int my=now->r.my(); if(x<=mx) { if(y<=my) { if(now->son[0]==nil) now->son[0]=Create(retange(now->r.x1,now->r.y1,mx,my)); now=now->son[0]; } else { if(now->son[1]==nil) now->son[1]=Create(retange(now->r.x1,my+1,mx,now->r.y2)); now=now->son[1]; } } else { if(y<=my) { if(now->son[2]==nil) now->son[2]=Create(retange(mx+1,now->r.y1,now->r.x2,my)); now=now->son[2]; } else { if(now->son[3]==nil) now->son[3]=Create(retange(mx+1,my+1,now->r.x2,now->r.y2)); now=now->son[3]; } } now->sum+=n; if(now->r.ok())break; } } LL Query(retange r, Node *now) { if(r.cover(now->r))return now->sum; LL ret=0; REP(i,4) if(now->son[i]!=nil&&now->son[i]->r.interset(r)) ret+=Query(r,now->son[i]); return ret; } char s[333]; int main() { freopen("a","r",stdin); //freopen("wa","w",stdout); Node *root=Create(retange(0,0,20001,20001)); retange r; int op,x,y,n; while(gets(s)) { if(s[0]=='E') { C=mem; root=Create(retange(0,0,20001,20001)); continue; } if(s[0]=='I') { op=1; continue; } if(s[0]=='Q') { op=0; continue; } if(op) { sscanf(s,"%d%d%d",&x,&y,&n); Update(x,y,n,root); } else { r.rd(s); printf("%lld\n",Query(r,root)); } } return 0; }