题面

题解

因为强制在线,所以我们不能$cdq$分治,所以考虑用$KDT$,$KDT$维护一个矩阵,然后询问的时候如果当前矩形在询问区间内,直接记贡献,否则判断当前点是否在矩阵内,然后左右分别递归下去判断就行了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::nth_element;
typedef long long ll; template<typename T>
void read(T &x) {
int flag = 1; x = 0; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
} const int N = 200005;
int n, x1, x2, y1, y2, k, ans, rt, WD, top, cnt, rub[N];
struct poi { int x[2], w; } p[N];
struct node { int mi[2], mx[2], sum, lc, rc, siz; poi tp; } t[N];
int operator < (const poi &a, const poi &b) { return a.x[WD] < b.x[WD]; }
inline int newnode() { if(top) return rub[top--]; else return ++cnt; }
void up(int k) {
int l = t[k].lc, r = t[k].rc;
for(int i = 0; i < 2; ++i) {
t[k].mi[i] = t[k].mx[i] = t[k].tp.x[i];
if(l) t[k].mi[i] = min(t[k].mi[i], t[l].mi[i]), t[k].mx[i] = max(t[k].mx[i], t[l].mx[i]);
if(r) t[k].mi[i] = min(t[k].mi[i], t[r].mi[i]), t[k].mx[i] = max(t[k].mx[i], t[r].mx[i]);
}
t[k].sum = t[l].sum + t[r].sum + t[k].tp.w, t[k].siz = t[l].siz + t[r].siz + 1;
}
int build(int l, int r, int wd) {
if(l > r) return 0;
int mid = (l + r) >> 1, k = newnode();
WD = wd, nth_element(p + l, p + mid, p + r + 1), t[k].tp = p[mid];
t[k].lc = build(l, mid - 1, wd ^ 1), t[k].rc = build(mid + 1, r, wd ^ 1);
up(k); return k;
}
void pia(int k, int num) {
if(t[k].lc) pia(t[k].lc, num);
p[t[t[k].lc].siz + num + 1] = t[k].tp, rub[++top] = k;
if(t[k].rc) pia(t[k].rc, num + t[t[k].lc].siz + 1);
}
void check(int &k, int wd) {
if(0.75 * t[k].siz < t[t[k].lc].siz || 0.75 * t[k].siz < t[t[k].rc].siz)
pia(k, 0), k = build(1, t[k].siz, wd);
}
void insert(int &k, poi tmp, int wd) {
if(!k) { k = newnode(), t[k].lc = t[k].rc = 0, t[k].tp = tmp, up(k); return ; }
if(tmp.x[wd] <= t[k].tp.x[wd]) insert(t[k].lc, tmp, wd ^ 1);
else insert(t[k].rc, tmp, wd ^ 1);
up(k), check(k, wd);
}
int in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2) { return (X1>=x1&&X2<=x2&&Y1>=y1&&Y2<=y2); }
int out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2) { return (x1>X2||x2<X1||y1>Y2||y2<Y1); }
int query(int k, int x1, int y1, int x2 ,int y2) {
if(!k) return 0;
int ret = 0;
if(in(x1, y1, x2, y2, t[k].mi[0], t[k].mi[1], t[k].mx[0], t[k].mx[1])) return t[k].sum;
if(out(x1, y1, x2, y2, t[k].mi[0], t[k].mi[1], t[k].mx[0], t[k].mx[1])) return 0;
if(in(x1, y1, x2, y2, t[k].tp.x[0], t[k].tp.x[1], t[k].tp.x[0], t[k].tp.x[1])) ret += t[k].tp.w;
return ret + query(t[k].lc, x1, y1, x2, y2) + query(t[k].rc, x1, y1, x2, y2);
} int main () {
read(n);
while(true) {
int opt; read(opt);
if(opt == 3) break;
else {
read(x1), read(y1), x1 ^= ans, y1 ^= ans;
if(opt == 1) read(k), insert(rt, (poi){x1, y1, k ^ ans}, 0);
else {
read(x2), read(y2), x2 ^= ans, y2 ^= ans;
ans = query(rt, x1, y1, x2, y2), printf("%d\n", ans);
}
}
}
return 0;
}

Luogu P4148 简单题(K-D Tree)的更多相关文章

  1. luogu P4148 简单题

    传送门 这题真简单,直接把\(CDQ\)给ban掉了 其实数据范围比较小可以直接二维树状数组,我们看数据范围,发现点的个数比N还小,可以考虑用一些奇怪的数据结构 说的就是你,\(KD tree\) \ ...

  2. 洛谷 P4148 简单题 解题报告

    P4148 简单题 题意 维护单点加与矩形求和,强制在线 说明 \(n\le 500000,m\le 200000\),\(4000ms / 20MB\) kd-tree 复杂度我不懂 是一颗平衡树, ...

  3. 洛谷 P4148 简单题 KD-Tree 模板题

    Code: //洛谷 P4148 简单题 KD-Tree 模板题 #include <cstdio> #include <algorithm> #include <cst ...

  4. 简单题(K-D Tree)

    简单题不简单-- 我们把单点加操作改成插入一个权值为增加量的点,将问题转化成询问一个矩阵中所有点的和,用 \(K-D\ Tree\) 维护,时间复杂度 \(O(n\sqrt{n})\) \(Code\ ...

  5. P4148 简单题 k-d tree

    思路:\(k-d\ tree\) 提交:2次 错因:整棵树重构时的严重错误:没有维护父子关系(之前写的是假重构所以没有维护父子关系) 题解: 遇到一个新的点就插进去,如果之前出现过就把权值加上. 代码 ...

  6. P4148 简单题(KDTree)

    传送门 KDTree 修改权值当做插入节点,不平衡就暴力重构,询问的时候判断当前节点代表的矩形是否在询问的矩形的,是的话返回答案,相离返回0,否则的话判断当前点是否在矩形内,然后继续递归下去 //mi ...

  7. BZOJ4066:简单题(K-D Tree)

    Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:   命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 ...

  8. acm.njupt 1001-1026 简单题

    点击可展开上面目录 Acm.njupt 1001-1026简单题 第一页许多是简单题,每题拿出来说说,没有必要,也说不了什么. 直接贴上AC的代码.初学者一题题做,看看别人的AC代码,寻找自己的问题. ...

  9. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

随机推荐

  1. 51Nod 1014 X^2 Mod P

    注意潜在范围 x*x用long long #include <bits/stdc++.h> using namespace std; typedef long long LL; #defi ...

  2. POJ 2891- Strange Way to Express Integers CRT 除数非互质

    题意:给你余数和除数求x 注意除数不一定互质 思路:不互质的CRT需要的是将两个余数方程合并,需要用到扩展GCD的性质 合并互质求余方程 m1x -+ m2y = r2 - r1 先用exgcd求出特 ...

  3. [Luogu 2805] NOI2009 植物大战僵尸

    这题是个比较经典的最大权闭合子图,可以建图转化为最小割问题,再根据最大流最小割定理,采用任意一种最大流算法求得. 对于每个点,如果点权w为正,则从源点到这个点连一条边权为w的有向边:否则如果w为负则从 ...

  4. Linux和windows下检查jsp后门文件的方法

    Linux下: find . -name "*.jsp" | xargs egrep -liw "createNewFile| File\(| File |applica ...

  5. 「6月雅礼集训 2017 Day5」仰望星空

    [题目大意] 给你$n$个点,被一个半径为$R$的元圆划分成内(包含边界).外两个部分. 要连若干线,每个点只能连一条线,不存在重点和三点共线. 线只能连在内部点和外部点之间,线长度不超过$d$. 如 ...

  6. SpringBoot Mybatis 读写分离配置(山东数漫江湖)

    为什么需要读写分离 当项目越来越大和并发越来大的情况下,单个数据库服务器的压力肯定也是越来越大,最终演变成数据库成为性能的瓶颈,而且当数据越来越多时,查询也更加耗费时间,当然数据库数据过大时,可以采用 ...

  7. 基于springmvc静态文件资源配置问题

    1.在这里只教大家一种非常实用的 比较简单的一种: 如果两种都配置记得注释掉这种:

  8. python基础===字符串切片

    字符串的子串可以通过切片标志来表示:两个由冒号隔开的索引. >>> word 'HelpA' >>> word[4] 'A' >>> word[0 ...

  9. 【模板】BZOJ 3781: 小B的询问 莫队算法

    http://www.lydsy.com/JudgeOnline/problem.php?id=3781 N个数的序列,每次询问区间中每种数字出现次数的平方和,可以离线. 丢模板: #include ...

  10. 海量文件查重SimHash和Minhash

    SimHash 事实上,传统比较两个文本相似性的方法,大多是将文本分词之后,转化为特征向量距离的度量,比如常见的欧氏距离.海明距离或者余弦角度等等.两两比较固然能很好地适应,但这种方法的一个最大的缺点 ...