洛谷 P2163 [SHOI2007]园丁的烦恼 (离线sort,树状数组,解决三维偏序问题)
P2163 [SHOI2007]园丁的烦恼
题目描述
很久很久以前,在遥远的大陆上有一个美丽的国家。统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草。
有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……”
“那么本质上它是一个深度优先搜索,陛下”,园丁深深地向国王鞠了一躬。
“嗯……我听说有一种怪物叫九头蛇,它非常贪吃苹果树……”
“是的,显然这是一道经典的动态规划题,早在N元4002年我们就已经发现了其中的奥秘了,陛下”。
“该死的,你究竟是什么来头?”
“陛下息怒,干我们的这行经常莫名其妙地被问到和OI有关的题目,我也是为了预防万一啊!” 王者的尊严受到了伤害,这是不可容忍的。
看来一般的难题是难不倒这位园丁的,国王最后打算用车轮战来消耗他的实力: “年轻人,在我的花园里的每一棵树可以用一个整数坐标来表示,一会儿,我的骑士们会来轮番询问你某一个矩阵内有多少树,如果你不能立即答对,你就准备走人吧!”说完,国王气呼呼地先走了。
这下轮到园丁傻眼了,他没有准备过这样的问题。所幸的是,作为“全国园丁保护联盟”的会长——你,可以成为他的最后一根救命稻草。
输入格式
第一行有两个整数n,m(0≤n≤500000,1≤m≤500000)。n代表皇家花园的树木的总数,m代表骑士们询问的次数。
文件接下来的n行,每行都有两个整数xi,yi,代表第i棵树的坐标(0≤xi,yi≤10000000)。
文件的最后m行,每行都有四个整数aj,bj,cj,dj,表示第j次询问,其中所问的矩形以(aj,bj)为左下坐标,以(cj,dj)为右上坐标。
输出格式
共输出m行,每行一个整数,即回答国王以(aj,bj)和(cj,dj)为界的矩形里有多少棵树。
输入输出样例
输入 #1复制
3 1
0 0
0 1
1 0
0 0 1 1
输出 #1复制
3
思路:
三维偏序解决二维平面中矩形包括多少个点数问题。
维度:
{
x轴
y轴
操作类型
}
我们把初始给定的n个点转为向坐标系中加点的操作
m个询问转为询问问题。
那么按照x,y升序排序,想x和y都相等时,加点的操作优先。
通过二维前缀和性质,把询问分解为四个(0,0)节点为左下角子询问积累贡献求得。
排序后,利用树桩数组来维护答案。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline void getInt(int *p);
const int maxn = 3000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll tree[maxn];
int lowbit(int x)
{
return -x & x;
}
ll ask(int x)
{
ll res = 0ll;
while (x) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
int my=0;
void add(int x, ll val)
{
while (x < my) {
tree[x] += val;
x += lowbit(x);
}
}
pii a[maxn];
pii b[maxn];
pii c[maxn];
int n, m;
std::vector<int> vx,vy;
struct node {
int op;
int x, y;
int k;
int id;
node() {}
node(int opp, int xx, int yy, int kk, int idd)
{
op = opp;
x = xx;
y = yy;
k = kk;
id = idd;
}
} info[maxn];
int ans[maxn];
bool cmp(node aa, node bb)
{
if (aa.x != bb.x) {
return aa.x < bb.x;
} else if (aa.op != bb.op) {
return aa.op < bb.op;
} else {
return aa.y < bb.y;
}
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin >> n >> m;
repd(i, 1, n) {
cin >> a[i].fi >> a[i].se;
vx.push_back(a[i].fi);
vy.push_back(a[i].se);
}
repd(i, 1, m) {
cin >> b[i].fi >> b[i].se >> c[i].fi >> c[i].se;
vx.push_back(b[i].fi);
vy.push_back(b[i].se);
vx.push_back(c[i].fi);
vy.push_back(c[i].se);
vy.push_back(b[i].se - 1);
vx.push_back(b[i].fi - 1);
}
sort(ALL(vx));
sort(ALL(vy));
vx.erase(unique(ALL(vx)),vx.end());
vy.erase(unique(ALL(vy)),vy.end());
my=sz(vy)+10;
int cnt = 0;
int dx, dy;
repd(i, 1, n) {
++cnt;
dx = lower_bound(ALL(vx), a[i].fi) - vx.begin() + 1;
dy = lower_bound(ALL(vy), a[i].se) - vy.begin() + 1;
info[cnt] = node(0, dx, dy, 0, 0);
}
repd(i, 1, m) {
++cnt;
dx = lower_bound(ALL(vx), c[i].fi) - vx.begin() + 1;
dy = lower_bound(ALL(vy), c[i].se) - vy.begin() + 1;
info[cnt] = node(1, dx, dy, 1, i);
++cnt;
dx = lower_bound(ALL(vx), c[i].fi) - vx.begin() + 1;
dy = lower_bound(ALL(vy), b[i].se - 1) - vy.begin() + 1;
info[cnt] = node(1, dx, dy, -1, i);
++cnt;
dx = lower_bound(ALL(vx), b[i].fi - 1) - vx.begin() + 1;
dy = lower_bound(ALL(vy), c[i].se) - vy.begin() + 1;
info[cnt] = node(1, dx, dy, -1, i);
++cnt;
dx = lower_bound(ALL(vx), b[i].fi-1) - vx.begin() + 1;
dy = lower_bound(ALL(vy), b[i].se-1) - vy.begin() + 1;
info[cnt] = node(1, dx, dy, 1, i);
}
sort(info + 1, info + 1 + cnt, cmp);
repd(i, 1, cnt) {
if (!info[i].op) {
add(info[i].y, 1);
} else {
ans[info[i].id] += info[i].k * ask(info[i].y);
}
}
repd(i, 1, m) {
printf("%d\n", ans[i] );
}
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}
洛谷 P2163 [SHOI2007]园丁的烦恼 (离线sort,树状数组,解决三维偏序问题)的更多相关文章
- BZOJ1935或洛谷2163 [SHOI2007]园丁的烦恼
BZOJ原题链接 洛谷原题链接 很容易想到二维前缀和. 设\(S[i][j]\)表示矩阵\((0, 0)(i, j)\)内树木的棵数,则询问的矩形为\((x, y)(xx, yy)\)时,答案为\(S ...
- BZOJ 1935: [Shoi2007]Tree 园丁的烦恼( 差分 + 离散化 + 树状数组 )
假如矩阵范围小一点就可以直接用二维树状数组维护. 这道题, 差分答案, 然后一维排序, 另一维离散化然后树状数组维护就OK了. ----------------------------------- ...
- 洛谷 P1975 [国家集训队]排队 Lebal:块内排序+树状数组
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和. 红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- 洛谷 P2038 无线网络发射器选址 —— 二维树状数组
题目:https://www.luogu.org/problemnew/show/P2038 大水题暴露出我的愚蠢. 用二维树状数组,然而居然忘了它应该那样写,调了一个小时: 正方形可以超出外面,只要 ...
- P2163 [SHOI2007]园丁的烦恼
题目 P2163 [SHOI2007]园丁的烦恼 做法 关于拆点,要真想拆直接全部用树状数组水过不就好了 做这题我们练一下\(cdq\)分治 左下角\((x1,y1)\)右上角\((x2,y2)\), ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
- HDU 4746 莫比乌斯反演+离线查询+树状数组
题目大意: 一个数字组成一堆素因子的乘积,如果一个数字的素因子个数(同样的素因子也要多次计数)小于等于P,那么就称这个数是P的幸运数 多次询问1<=x<=n,1<=y<=m,P ...
- hdu-3333 Turing Tree 离线区间+树状数组(区间不同数的和)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 题目大意: 给出一数组,以及m个查询区间,每次查询该区间不同数字的和.相同数字只加一次. 解题 ...
随机推荐
- django 之(六) --- Celery|Admin
Celery - 分布式任务队列 简介: Celery是一个简单,灵活且可靠的分布式系统,可以处理大量消息,同时为操作提供维护该系统所需的工具.这是一个任务队列,着重于实时处理,同时还支持任务调度. ...
- 【AMAD】django-reversion -- 为django的model实例带来版本控制
动机 简介 个人评分 动机 有时候数据表的数据也需要版本控制.比如论坛的帖子,作者是可以改动的,但是你想要留下每个改动的版本. 简介 django-reversion1的特点: 可以回滚一个insta ...
- 【编程开发】opencv实现对Mat中某一列或某一行的元素进行normalization
[编程开发]opencv实现对Mat中某一列或某一行的元素进行normalization 标签: [编程开发] [机器学习] 声明:引用请注明出处http://blog.csdn.net/lg1259 ...
- Java 中 try、catch、finally 语句块的执行顺序
假设代码顺序书写如下:try → catch → finally → 其他代码 则: 1.正常执行顺序:try → catch → finally → 其他代码 2.try,catch和finally ...
- Spring 控制器层如何调用DAO层
1.写上注解 @Autowired 2.声明一个变量 private UserDao userDao; 3.注意!Spring里面数据库对象操作类不需要实例化就能调用
- Reactor系列(七)flatMap映射
#java##reactor##flatMap# 视频讲解: https://www.bilibili.com/video/av79582009/ FluxMonoTestCase.java pack ...
- javascript let
es6支持通过let关键字声明属于单独块{}的变量,更好的管理变量作用屿 funtion foo() { var a=1; if (a>1) { let b=2; //只属于if模块 while ...
- Netty学习篇①
什么是netty Netty封装了JDK自带的NIO,运用起来更加简单快速,Netty是一个异步事件驱动的网络应用框架,让开发更加简便 Netty相比JDK自带的NIO的优点 Netty的api调用简 ...
- UWP笔记-自定义Grid背景图片
之前写简单的UWP版本地音乐播放器,有自定义背景壁纸的功能,现在贴在这里回顾下. Page.xaml 页面,添加Grid <Grid x:Name="mainGrid"/&g ...
- 【AtCoder】AGC034
AGC034 刷了那么久AtCoder我发现自己还是只会ABCE(手动再见 A - Kenken Race 大意是一个横列,每个点可以跳一步或者跳两步,每个格子是空地或者石头,要求每一步不能走到石头或 ...