【K-D树 求矩阵的和】BZOJ-4066 简单题
来源:互联网 发布:欧洲神话 巨人 知乎 编辑:程序博客网 时间:2024/05/05 19:51
Problem Description
输入一个N,代表有一个N*N的棋盘。
有三种操作
1 x y A : 将格子x, y里的数字加上A
2 xl yl xr yr : 输出xl yl xr yr这个矩阵内的数字和(xl <= xr, yl <= yr)
3 : 终止条件
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
对于每个2操作,输出一个对应的答案。
思路:
学习ldq的思路
这里插入的点的数量有点多,可能导致树的形态太差,所以插入点树每过 5000 就暴力重构一下。
注意求矩阵和函数,和线段树区间求和 还是有点相似的。
其他函数基本不变
#include<bits/stdc++.h>using namespace std;const int MAX = 200055;const int inf = 0x3f3f3f3f;const int DIM = 2;struct node{ int l, r; int sum, v;//sum记录这个子树的和,v代表该点的值 int d[DIM], maxn[DIM], minn[DIM]; inline void maintain()//初始化 { for(int i = 0; i < DIM; i++) maxn[i] = minn[i] = d[i]; l = r = 0; sum = v; }} tree[MAX*2];int D;bool operator < (const node &a, const node &b)//重载从小到大{ return a.d[D] < b.d[D];}inline void Merge(int o)//归并,向上更新{ int son[2] = {tree[o].l, tree[o].r}; for(int i = 0; i < 2; i++) { if(!son[i]) continue; for(int j = 0; j < DIM; j++) { tree[o].maxn[j] = max(tree[o].maxn[j], tree[son[i]].maxn[j]); tree[o].minn[j] = min(tree[o].minn[j], tree[son[i]].minn[j]); } } tree[o].sum = tree[o].v + tree[son[0]].sum + tree[son[1]].sum;}int build(int l, int r, int now)//建树{ int mid = (l+r) >> 1; D = now; nth_element(tree+l, tree+mid, tree+r+1); tree[mid].maintain(); if(l < mid) tree[mid].l = build(l, mid-1, (now+1)%DIM); if(r > mid) tree[mid].r = build(mid+1, r, (now+1)%DIM); Merge(mid); return mid;}void Insert(int &o, int k, int now)//插入{ if(o == 0) { o = k; return ; } if(tree[k].d[now] < tree[o].d[now]) Insert(tree[o].l, k, (now+1)%DIM); else Insert(tree[o].r, k, (now+1)%DIM); Merge(o);}int xl, xr, yl, yr;int ans;void query(int o)//求和{ if(xr < tree[o].minn[0] || xl > tree[o].maxn[0] || yl > tree[o].maxn[1] || yr < tree[o].minn[1])//这个子树,不在所求范围内 return; if(xl <= tree[o].minn[0] && xr >= tree[o].maxn[0] && yl <= tree[o].minn[1] && yr >= tree[o].maxn[1])//所求范围,包含子树 { ans += tree[o].sum; return; } if(xl <= tree[o].d[0] && xr >= tree[o].d[0] && yl <= tree[o].d[1] && yr >= tree[o].d[1])//部分包含 ans += tree[o].v; if(tree[o].l) query(tree[o].l); if(tree[o].r) query(tree[o].r);}int read(){ int t; scanf("%d", &t); return ans^t;}int main(){ int n; scanf("%d", &n); int pos = 1, op; int root = 0; ans = 0; while(true) { scanf("%d", &op); if(op == 1) { for(int i = 0; i < DIM; i++) tree[pos].d[i] = read(); tree[pos].v = read(); tree[pos].maintain(); Insert(root, pos, 0); pos++; if(pos % 5000 == 0) root = build(1, pos-1, 0); } else if(op == 2) { xl = read(); yl = read(); xr = read(); yr = read(); ans = 0; query(root); printf("%d\n", ans); } else break; } return 0;}
阅读全文
0 0
- 【K-D树 求矩阵的和】BZOJ-4066 简单题
- bzoj 4066: 简单题 k-d tree
- 求累加和小于等于k的最大子矩阵
- 【K-D树 求最近最远距离】BZOJ 1941 [Sdoi2010]Hide and Seek
- BZOJ 2626 JZPFAR K-D树
- 【裸K-D树】BZOJ 2648
- F题 求最大矩阵的和
- matlab求矩阵前k小的特征值和对应的特征向量
- POJ 3233 Matrix Power Series(矩阵求A+…+A^k 的和)
- 4066: 简单题 K-D tree重构
- Codeforeces 501D 平衡树求排名和第k大
- [bzoj]郁闷的出纳员[Splay求第k大]
- BZOJ 1941 SDOI 2010 Hide and Seek K-D树
- 八叉树及K-D树的应用和实现
- 八叉树及K-D树的应用和实现
- 八叉树及K-D树的应用和实现
- 八叉树及K-D树的应用和实现
- 八叉树及K-D树的应用和实现
- android EditText能获取焦点但禁用所有输入法
- windows netstat 查看端口、进程占用
- Java实现Hadoop大表join
- dataframe.replace re.sub() 替换练习
- 欢迎使用CSDN-markdown编辑器
- 【K-D树 求矩阵的和】BZOJ-4066 简单题
- Windows下,JAVA-protobuf-3.5.0
- Mysql循环查询结果并设置排序编号
- 调用接口,解析返回的的string类型xml文档
- LDAP的相关概念与objectClass介绍
- C语言简单迷宫问题,深搜,通俗易懂。
- Android 不Root查看App /data/data/目录文件
- Codeforces Round #448 (Div. 2) A. Pizza Separation
- 数据库开发(MySql)