Codeforces Round #216 (Div. 2) E. Valera and Queries 树状数组 离线处理
2015-10-08 14:14
489 查看
题意:n个线段[Li, Ri], m次询问, 每次询问由cnt个点组成,输出包含cnt个点中任意一个点的线段的总数。
由于是无修改的,所以我们首先应该往离线上想, 不过我是没想出来。
首先反着做,先求不包含这个cnt个点的线段的总数, 那么不包含这些点的线段必然在cnt个点之间(这里需要再加两个点一个是0, 一个是MAX),
我们可以把所有线段按Ri 分类, 然后按右端点遍历,对于当前的线段可以在Li 处+1, 然后对于每一次询问中两个点(x, y)之间线段的个数,
只需要查询 左端点大于等于x的个数就好了,这里因为是按右端点从小到大遍历的,所以不用考虑用端点了。
发现, 大多数的离线处理都是先把其中的一维从小到大排序, 然后处理另一维。 这样相当于降维。
由于是无修改的,所以我们首先应该往离线上想, 不过我是没想出来。
首先反着做,先求不包含这个cnt个点的线段的总数, 那么不包含这些点的线段必然在cnt个点之间(这里需要再加两个点一个是0, 一个是MAX),
我们可以把所有线段按Ri 分类, 然后按右端点遍历,对于当前的线段可以在Li 处+1, 然后对于每一次询问中两个点(x, y)之间线段的个数,
只需要查询 左端点大于等于x的个数就好了,这里因为是按右端点从小到大遍历的,所以不用考虑用端点了。
发现, 大多数的离线处理都是先把其中的一维从小到大排序, 然后处理另一维。 这样相当于降维。
#include <bits/stdc++.h> const int maxn = 1e6 + 10; typedef std::pair <int, int> pii; std::vector <int> seg[maxn], q[maxn]; std::vector <pii> rq[maxn]; namespace FenwickTree{ int arr[maxn]; void inc(int x, int d){ while (x < maxn){ arr[x] += d; x += x & -x; } } int query(int x){ int res = 0; while (x > 0){ res += arr[x]; x -= x & -x; } return res; } int query(int ua, int ub){ return query(ub) - query(ua-1); } } int ans[maxn]; void init(){ memset(ans, 0, sizeof (ans)); for (int i = 0; i < maxn; i++){ seg[i].clear(); q[i].clear(); rq[i].clear(); } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif // ONLINE_JUDGE int n, m; while (~ scanf ("%d%d", &n, &m)){ init(); for (int i = 0; i < n; i++){ int ua, ub; scanf("%d%d", &ua, &ub); ua++, ub++; seg[ub].push_back(ua); } for (int i = 0; i < m; i++){ int cnt, p; scanf ("%d", &cnt); q[i].push_back(1); while (cnt--){ scanf ("%d", &p); p++; q[i].push_back(p); } q[i].push_back(maxn-1); for (int j = 0; j < q[i].size()-1; j++){ int ua = q[i][j]+1; int ub = q[i][j+1]-1; rq[ub].push_back(std::make_pair(ua, i)); } } for (int i = 1; i < maxn; i++){ for (int j = 0; j < seg[i].size(); j++){ int tmp = seg[i][j]; FenwickTree::inc(seg[i][j], 1); } for (int j = 0; j < rq[i].size(); j++){ int idx = rq[i][j].second; int tmp = rq[i][j].first; ans[idx] += FenwickTree::query(rq[i][j].first, i); } } for (int i = 0; i < m; i++){ printf("%d\n", n - ans[i]); } } return 0; }
相关文章推荐
- Android GUI之Window、WindowManager
- UI_动画-UIView属性动画、block块、仿设变换、CAAnimation
- UIGestureRecognizer手势
- POJ 2533 Longest Ordered Subsequence (LIS)
- 使用UINib加载xib文件实现UITableViewCell
- 1007. Maximum Subsequence Sum (25)
- SparkSQL05_prepareForExecution_01_EnsureRequirements
- 【转载】今天心情非常好,再发一组 Linq、 集合、数组、Lambda、QuerySyntax 的文章
- UIActionSheet的最后一项点击失效
- 修改IOS中UISearchBar的取消按钮及所有视图看了其他的文章都不试一下就发出来,更本就存在些纰漏,下面是我做了稍许修改的结果:
- easyUI日历
- POJ 3566 Building for UN (无脑构造 水题)
- Integer.toString()与String.valueOf(Oject)有什么不同(2015年10月8日)
- Visual Studio: whether auto-building when press the debug button
- Android中startActivity中的permission检测与UID机制
- PHP设计模式——建造者模式(builder)
- 修改SVN的UUID
- IOS和安卓ui设计常用尺寸及基本知识
- 彻底解决Request Too Long的问题
- UI_UItabBarController