我是萌萌的传送门

题意不难理解吧……

一开始看到这道题的时候lrd告诉我这题要分治,还给我讲了讲分治要怎么写,好像是CDQ+树状数组来着……(好吧我已经忘了……)然而我第一眼看完题之后的思路是数据结构直接搞,本着“我就不信这个邪了”的念头,就搞出了这么一个树状数组套平衡树维护斜线的奇葩写法。

话说lrd说这题卡常,然而限时40s,我23.8s并没有什么压力,不过运行速度倒数也是感人肺腑……

(我后面就这么几个了……数据结构果然比不上CDQ……QAQ)

言归正传。

如果不用分治的话就需要按照x或者y扫描所有点,并依次处理当前点与之前的点形成的贡献和更新数据结构。

显然对于每个点,对它有贡献的点只能是在它左下角且它的右上角没有其他点的点,如图:

把这些点用线段连起来,可以得到一条斜率始终为负的斜线。如果按照y坐标从小到大处理的话,就可以以y坐标为关键字建立平衡树维护斜线。

每次查询都是前缀查询,直接在平衡树中查询即可。但是会发现一些反例,例如:

如果先插入红点的话,按照定义应该把斜线清空,只留下红点,然后查询绿点的时候就会WA。

这说明,每插入一个新点就会破坏斜线。也就是说,我们在询问的时候必须只考虑x坐标在当前点左边的点,因为按照y递增处理,只能用一个数据结构维护x。考虑到每个询问都是前缀询问,可以对x离散化后用树状数组维护x坐标,再用平衡树维护位于对应区间内的斜线即可。

查询和更新应该不难想,贴两个图跑算了。

懒得写Treap了,所以用了pb_ds……如果Treap的话还要手写删除所有键值>x的数,有空再说……

 /**************************************************************
Problem: 4237
User: hzoier
Language: C++
Result: Accepted
Time:23888 ms
Memory:70456 kb
****************************************************************/ #include<cstdio>
#include<cstring>
#include<algorithm>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<int,int,less<int>,rb_tree_tag,tree_order_statistics_node_update>rbtree;
const int maxn=;
struct A{
int x,y;
bool operator<(const A &a)const{return y<a.y;}
}a[maxn];
void add(int,int);
int query(int);
int n,b[maxn];
long long ans=;
rbtree T[maxn];
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
b[i]=a[i].x;
}
sort(b+,b+n+);
for(int i=;i<=n;i++)a[i].x=lower_bound(b+,b+n+,a[i].x)-b;
sort(a+,a+n+);
for(int i=;i<=n;i++){
ans+=query(a[i].x);
add(a[i].x,a[i].y);
}
printf("%lld",ans);
return ;
}
void add(int x,int y){
for(int i=x;i<=n;i+=i&-i){
rbtree::reverse_iterator it=T[i].rbegin();
while(it!=T[i].rend()&&it->second<x){
rbtree::reverse_iterator iter=++it;
T[i].erase(--it);
it=iter;
}
T[i][y]=x;
}
}
int query(int x){
int ans=,y=-;
while(x){
ans+=T[x].size()-T[x].order_of_key(y);
if(!T[x].empty())y=max(y,T[x].rbegin()->first);
x&=x-;
}
return ans;
}

话说这题是一边听教练放歌一边写的,结果费了两节课,这种简单题写这么久,身败名裂……

bzoj4237 稻草人的更多相关文章

  1. bzoj4237: 稻草人 cdq分治 单调栈

    目录 题目链接 题解 代码 题目链接 bzoj4237: 稻草人 题解 暴力统计是n^2的 考虑统计一段区间对另一端的贡献 对于y值cdq分治,降调一维 对于当前两个分治区间统计上面那部分对下面那部分 ...

  2. [BZOJ4237]稻草人/[JOISC2014]かかし

    [BZOJ4237]稻草人/[JOISC2014]かかし 题目大意: 平面上\(n(n\le2\times10^5)\)个点,若一个矩形各边与坐标轴平行,左下角和右上角都在\(n\)个点之中,且内部不 ...

  3. BZOJ4237 稻草人 分治 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/8682572.html 题目传送门 - BZOJ4237 题意 平面上有$n(n\leq 2\times 10^ ...

  4. [BZOJ4237]稻草人(CDQ分治)

    先按y排序,二分,两边递归下去,然后处理下半部分对上半部分的贡献,即左下点在下半部分,右上点在上半部分的合法矩形个数. 两个部分均按x排序,枚举右上点p,则左下点需要满足: 1.横坐标大于上半部分纵坐 ...

  5. BZOJ4237 稻草人 【CDQ分治】

    Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要 ...

  6. BZOJ4237 稻草人(分治+树状数组+单调栈)

    如果要询问的某个纵坐标为inf的点左边是否有点能与其构成所要求的矩形,只要用个单调栈就可以了.可以想到用分治来制造单调性. 按横坐标排序,每次考虑跨过分治中心的矩形.考虑右边的每个点能与左边的哪些点构 ...

  7. BZOJ4237稻草人——单调栈+CDQ分治

    题目描述 JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: ...

  8. bzoj4237稻草人

    题意:给你一个田地,问左下角和右上角有稻草人并且内部除了边界都没有稻草人的矩形数. 标程: #include<bits/stdc++.h> using namespace std; int ...

  9. bzoj4237 稻草人——分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4237 分治: 先把所有点按 y 排序,然后二分递归: 对于每个 mid ,计算经过它的矩形的 ...

随机推荐

  1. [LeetCode] Second Highest Salary 第二高薪水

    Write a SQL query to get the second highest salary from the Employee table. +----+--------+ | Id | S ...

  2. 学券制(教育券、school voucher)

    美国「学券制」是怎样的一种制度?它为什么是共和党的执政政策?它在美国及其它地区有实施吗?效果如何?能否在保证公平的同时,通过市场提高教育质量? 作者:冉筱韬链接:https://www.zhihu.c ...

  3. PPS传奇生死

    地址 :http://game.pps.tv/events/cqss_sign 调用encryptedString('password') RSA加密,通过function(a) 定义 window= ...

  4. bzoj1251

    1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3776  Solved: 1581[Submit][Status][Discu ...

  5. 关于List的ConcurrentModificationException

    对ArrayList的操作我们可以通过索引象来访问,也可以通过Iterator来访问,只要不对ArrayList结构上进行修改都不会造成ConcurrentModificationException, ...

  6. 马虎将classname加到了id属性中,造成报错

    今天做了一个瀑布流布局的小例子,自己在写代码的过程中一直报cannot read property 'style' of null,百度之后说是页面还没有加载完,但是我看了代码是写在window.on ...

  7. java学习笔记之正则表达式

    一般来说,正则表达式就是以某种方式来描述字符串,因此你可与说:"如果一个字符串符合有这些东西,那么它就是我正在找的东西. 1.要找一个数字,如果它可能有一个负号在最前面(可能没有,没有也是匹 ...

  8. linux下查看最消耗CPU、内存的进程

    2012-11-19 15:38:04 分类: LINUX 1.CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 2.内存消耗 ...

  9. ios小数向上、下取整,计算结果向上、下取整

    [摘要:小数背上与整,指小数局部间接进1 x=3.14, ceilf (x)=4 小数背下与整,指间接往失落小数局部 x=3.14,floor(x)=3 盘算效果背上与整 A被除数,B除数 ,(AB- ...

  10. 架构师养成记--9.future模式讲解

    什么是future模式呢?解释这个概念之前我们先来了解一个场景吧,财务系统的结账功能,这个功能可能是每个月用一次,在这一个月中相关的数据量已经积累得非常大,这一个功能需要调用好几个存储过程来完成.假如 ...