KD-Tree
KD-Tree的进阶姿势戳这里 http://zyfzyf.is-programmer.com/posts/92431.html
为啥有种线段树&平衡树的即视感……(树形结构的相似性?)
每次插入之后,判断下如果某个子树的size>父亲size*0.7,那么重构一下……(替罪羊树的即视感)
查询的时候,如果当前点表示的坐标范围被查询范围完全包含,则直接返回sum;
否则:当前点若在范围内则更新答案,左子树若不全在范围外则递归进入查询,右子树同理(线段树的即视感)
TLE:rebuild的时候,我没清当前点的min和max就直接build子树&Push_up(o)了……活该跪……
1 /************************************************************** 2 Problem: 4066 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:28400 ms 7 Memory:11444 kb 8 ****************************************************************/ 9 10 //BZOJ 4066 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-‘0‘+ch; 26 return r*v; 27 } 28 const int N=200010,INF=1e9; 29 /*******************template********************/ 30 int n,m,ans,D,cnt,p[N],tot,root; 31 struct node{ 32 int d[2],mn[2],mx[2],l,r,D,size,sum,v; 33 int& operator [] (int x){return d[x];} 34 }t[N],now; 35 inline bool cmp(int x,int y){return t[x][D]<t[y][D];} 36 37 #define L t[o].l 38 #define R t[o].r 39 #define mid (l+r>>1) 40 inline void Push_up(int o){ 41 F(i,0,1){ 42 t[o].mn[i]=min(t[o].mn[i],min(t[L].mn[i],t[R].mn[i])); 43 t[o].mx[i]=max(t[o].mx[i],max(t[L].mx[i],t[R].mx[i])); 44 } 45 t[o].sum=t[L].sum+t[R].sum+t[o].v; 46 t[o].size=t[L].size+t[R].size+1; 47 } 48 inline int build(int l,int r,int dir){ 49 D=dir; 50 nth_element(p+l,p+mid,p+r+1,cmp); 51 int o=p[mid]; 52 t[o].D=dir; 53 F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i]; 54 t[o].sum=t[o].v; 55 L=l<mid ? build(l,mid-1,dir^1) : 0; 56 R=mid<r ? build(mid+1,r,dir^1) : 0; 57 Push_up(o); 58 return o; 59 } 60 inline void dfs(int o){ 61 if (!o) return; 62 dfs(L); 63 p[++cnt]=o; 64 dfs(R); 65 } 66 inline void rebuild(int &o){ 67 cnt=0; 68 dfs(o); 69 o=build(1,cnt,t[o].D); 70 } 71 inline void Insert(int &o,int dir){ 72 if (!o){ 73 o=++tot; t[o]=now; 74 F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i]; 75 t[o].D=dir; 76 t[o].size=1; 77 t[o].sum=t[o].v; 78 return; 79 } 80 if (now[dir]<t[o][dir]){ 81 Insert(L,dir^1); 82 Push_up(o); 83 if ((double)t[L].size>(double)t[o].size*0.7) rebuild(o); 84 } 85 else{ 86 Insert(R,dir^1); 87 Push_up(o); 88 if ((double)t[R].size>(double)t[o].size*0.7) rebuild(o); 89 } 90 } 91 int query(int o,int x1,int y1,int x2,int y2){ 92 if (!o) return 0; 93 if (t[o].mn[0]>=x1 && t[o].mn[1]>=y1 && t[o].mx[0]<=x2 && t[o].mx[1]<=y2) 94 return t[o].sum; 95 else{ 96 int ans=0; 97 if (t[o][0]>=x1 && t[o][0]<=x2 && t[o][1]>=y1 && t[o][1]<=y2) ans+=t[o].v; 98 if (t[L].mn[0]>x2 || t[L].mx[0]<x1 || t[L].mn[1]>y2 || t[L].mx[1]<y1) ; 99 else ans+=query(L,x1,y1,x2,y2); 100 if (t[R].mn[0]>x2 || t[R].mx[0]<x1 || t[R].mn[1]>y2 || t[R].mx[1]<y1) ; 101 else ans+=query(R,x1,y1,x2,y2); 102 return ans; 103 } 104 } 105 void print(int o){ 106 if (!o) return; 107 printf("%d t[o].mn[0]=%d t[o].mn[1]=%d t[o].mx[0]=%d t[o].mx[1]=%d\n",o,t[o].mn[0],t[o].mn[1],t[o].mx[0],t[o].mx[1]); 108 print(L); 109 print(R); 110 } 111 int main(){ 112 #ifndef ONLINE_JUDGE 113 freopen("4066.in","r",stdin); 114 freopen("4066.out","w",stdout); 115 #endif 116 F(i,0,1) t[0].mn[i]=INF,t[0].mx[i]=-INF; 117 t[0].size=t[0].sum=t[0].v=0; 118 119 n=getint(); int cmd; 120 while(scanf("%d",&cmd)!=EOF && cmd<3){ 121 if (cmd==1){ 122 now[0]=getint()^ans,now[1]=getint()^ans,now.v=getint()^ans; 123 Insert(root,1); 124 }else{ 125 int x1=getint()^ans,y1=getint()^ans,x2=getint()^ans,y2=getint()^ans; 126 printf("%d\n",ans=query(root,x1,y1,x2,y2)); 127 } 128 } 129 return 0; 130 }
4066: 简单题
Time Limit: 50 Sec Memory Limit: 20 MB
Submit: 297 Solved: 99
[Submit][Status][Discuss]
Description
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 |
参数限制 |
内容 |
1 x y A |
1<=x,y<=N,A是正整数 |
将格子x,y里的数字加上A |
2 x1 y1 x2 y2 |
1<=x1<= x2<=N 1<=y1<= y2<=N |
输出x1 y1 x2 y2这个矩形内的数字和 |
3 |
无 |
终止程序 |
Input
输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
3
5
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
样例解释见OJ2683
Source
时间: 2024-10-05 09:32:11