LOJ #6270. 数据结构板子题 (离线+树状数组)
题意
有 \(n\) 个区间,第 \(i\) 个区间是 \([l_i,r_i]\) ,它的长度是 \(r_i-l_i\) 。
有 \(q\) 个询问,每个询问给定 \(L,R,K\) ,询问被 \([L,R]\) 包含的且长度不小于 \(K\) 的区间数量。
\(n,q≤500,000\)
题解
想了无数种 \(O((n+q) \log^2 n)\) 的做法啊TAT 后来看了 这份代码 后恍然大悟 .
这题一个很显然的想法是离线 qwq
首先离线 \(l ~or~ r\) 似乎不太可行 , 因为要动态支持查找一个区间 \([L, R]\) 不小于 \(K\) 的个数 , 而主席树需要离线完成 (划分树没学过 , 不知道可不可以) 在线的话只有 \(O(\log^2)\) 的复杂度可行了 .
那继续考虑离线 \(K\) , 然后这样的话 , 我们就可以忽略 \(K\) 的限制 .
假设我们当前算出了对于一个询问 所有长度 \(\le k\) 的区间个数 \(res_k\) , 那这个答案就可以表示成 \(res_n - res_{K-1}\) .
我们此时只需要做的就是 计算一个区间包含了当前的多少个区间 .
这个如何做呢 qwq
两个区间 \(A, B\) 只有三种情况 .
- \(A \subseteq B\) (此时 \(A\) 可以等于 \(B\) ) , \(B\) 完全包含 \(A\) , \(|B| \ge |A|\)
- \(A \not \subseteq B\) 且 \(B \not \subseteq A\) , 此时 \(A,B\) 交的部分不会是这两个区间中任意一个全集 .
- \(B \subseteq A ~(A\not = B)\) , \(A\) 完全包含 \(B\) , \(|A| > |B|\)
我们假设前面插入的区间为 \(A\) , 当前询问的区间为 \(B\) . 我们计算的就只有第 \(1\) 种情况了 .
不难发现 第 \(3\) 情况计数很麻烦 .
我们最好忽略第 \(3\) 种情况 , 只计算第 \(2\) 种情况 . (因为这个 \(A\) 会有两个出去不好计算)
不难发现长度会有限制 , 那我们询问的时候 只要询问所有 \(len \le R - L\) 的区间就行了 , 也就是每个离线后变成计算 \(res_{R-L} - res_{K - 1}\) .
而对于第 \(2\) 种情况 , \(A\) 只有一端会超出 \(B\) .
然后每次询问 \(res_i\) 的时候 假设当前插入的线段的总数是 \(tot\) .
答案显然就是 $tot - $ 前面左端点存在于 \([1, L - 1]\) 的线段个数 - 前面右端点存在于 \([R + 1, n]\) 的线段个数 .
(可以发现 , 这样很好地处理了两个线段相离的情况)
然后这个用两个树状数组统计一下 , 左端点和右端点各一个 .
所以最后的时间复杂度就是 \(O((n + q) \log n)\) 了 .
注意一开始离线的时候 要特判掉 \(R-L < K\) 的情况 !!
最好自己画图理解 , 博主懒就没放上来了qwq
代码
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ':' << x << endl
using namespace std;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("6270.in", "r", stdin);
freopen ("6270.out", "w", stdout);
#endif
}
const int N = 500100;
int n, q;
#define lowbit(x) (x & -x)
struct Fenwick_Tree {
int sumv[N];
inline void Update(int pos) { for(; pos <= n; pos += lowbit(pos)) ++ sumv[pos]; }
inline int Query(int pos) { int res = 0; for (; pos > 0; pos ^= lowbit(pos)) res += sumv[pos]; return res; }
} Pre, Suf;
struct Ask { int opt, l, r, id; } ;
typedef pair<int, int> PII;
#define fir first
#define sec second
vector<Ask> Q[N]; vector<PII> V[N]; int ans[N];
#define Rev(x) (n - (x) + 1)
int main () {
File();
n = read(); q = read();
For (i, 1, n) {
int l = read(), r = read(), len = r - l;
V[len].push_back(make_pair(l, r));
}
For (i, 1, q) {
int l = read(), r = read(), k = read(), len = r - l;
if (len >= k)
Q[k - 1].push_back((Ask) {-1, l, r, i}),
Q[len].push_back((Ask) {1, l, r, i});
}
int tot = 0;
For (i, 1, n) {
for (PII Up : V[i])
Pre.Update(Up.fir), Suf.Update(Rev(Up.sec)), ++ tot;
for (Ask Rp : Q[i])
ans[Rp.id] += Rp.opt * (tot - Pre.Query(Rp.l - 1) - Suf.Query(Rev(Rp.r + 1)));
}
For (i, 1, q) printf ("%d\n", ans[i]);
return 0;
}
LOJ #6270. 数据结构板子题 (离线+树状数组)的更多相关文章
- [LOJ 6270]数据结构板子题
Description 有n个区间,第i个区间是[li,ri],它的长度是ri−li. 有q个询问,每个询问给定L,R,K,询问被[L,R]包含的且长度不小于K的区间数量. 你想,像这种板子题,你随手 ...
- 【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇
歧义差评:但是和题意理解一样了之后细节依然处理了很久,说明还是水平不够…… 题目描述 Marisa来到了森林之中,看到了一排nn个五颜六色的蘑菇,编号从1-n1−n,这些蘑菇的颜色分别为col[1], ...
- SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)
DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...
- [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树)
[APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树) 题面 略 分析 首先把一组询问(x,y)看成二维平面上的一个点,我们想办法用数据结构维护这个二维平面(注意根据题意这 ...
- POJ 3416 Crossing --离线+树状数组
题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少 ...
- HDU 2852 KiKi's K-Number(离线+树状数组)
题目链接 省赛训练赛上一题,貌似不难啊.当初,没做出.离线+树状数组+二分. #include <cstdio> #include <cstring> #include < ...
- CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)
转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...
- 13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 2224: Boring Counting Time Limit: 3 Sec ...
- 区间的关系的计数 HDU 4638 离线+树状数组
题目大意:给你n个人,每个人都有一个id,有m个询问,每次询问一个区间[l,r],问该区间内部有多少的id是连续的(单独的也算是一个) 思路:做了那么多离线+树状数组的题目,感觉这种东西就是一个模板了 ...
随机推荐
- Github.Git
Github介绍:http://www.yangzhiping.com/tech/github.html Git:http://res.crossincode.com/wechat/git.html
- 在属性property做一些简单的验证
开发C#的程序,写到属性property时,我们可以在Set方法中做一些简单的规则验证: 如下面,Insus.NET写一个Age属性,只允许用户输入10以内的数字: class AA { privat ...
- 微信小程序 wx.getUserInfo 解密 C# 代码 - 转
public static string DecodeUserInfo(string raw, string signature,string encryptedData, string iv) { ...
- java内存模型与volatile变量与Atomic的compareAndSet
java分主内存和工作内存, 主内存是线程共享的, 工作内存是每个线程独有的. java对主内存的操作是通过工作内存间接完成的: 先拷贝主内存变量值到工作内存, 在工作内存操作这个变量的副本, 完成后 ...
- [Spark][python]以DataFrame方式打开Json文件的例子
[Spark][python]以DataFrame方式打开Json文件的例子: [training@localhost ~]$ cat people.json{"name":&qu ...
- iOS app签名原理
基本原理: 公钥能够验证私钥的签名是否正确. Apple后台有一个私钥A,iOS内置一个公钥A,与私钥A对应.(A:代表Apple,即苹果) 本地产生一对公钥L.私钥L,(L:代表Local,即本地) ...
- linux 与 windows 挖门罗币总结
比特币之前一直很火,初次了解的时候才2000RMB一枚..看不懂哇,错失良机...当然了,看得懂也不买不起..当时还是穷学生. 最近又一直看到黑客利用linux漏洞挖门罗币获利的新闻,决定好生研究一下 ...
- .NET持续集成与自动化部署之路第三篇——测试环境到生产环境的一键部署策略(Windows)
Jenkins测试环境到生产环境的一键部署策略(Windows) 一.前言 前面我们已经初步实现了开发集成环境.测试环境的持续集成(自动化构建.自动化测试.自动化部署).但生产环境自动化部署迟 ...
- 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID
---恢复内容开始--- 转:https://www.jianshu.com/p/38f4d1a4763b [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番 ...
- Docker容器学习梳理 - 基础环境安装
以下是centos系统安装docker的操作记录 1)第一种方法:采用系统自带的docker安装,但是这一般都不是最新版的docker安装epel源[root@docker-server ~]# wg ...