原文链接 https://www.cnblogs.com/cly-none/p/CERC2017B.html

题意:在一个网格平面上,有\(n\)个点,其中第\(i\)个点在以\((x_i, y_i)\)为右上角的网格中。有\(m\)次操作,每次给出一个点\((x,y)\),表示从\((x,y)\)开始,向左和向下画线直到与之前画的线或坐标轴相交。这样会划分出以\((x,y)\)为右上角的新区域。你需要对每次操作求出,新区域中点的数量。

$n , m \leq 3 \times 10^5, \ 1 \leq x_i, y_i \leq 10^9, $ 每次操作的 \(x\) 和 \(y\) 分别互不相同。

首先,我们容易得出各种\(O(n \log ^ 2n)\)的数据结构做法。然而,它们并没有太大的启发意义。

考虑离线下来,处理每个点对所有操作的贡献。

考虑求出每个点和操作最后是被哪个操作控制的。也就是能直接覆盖这个点(或操作)的操作中时间最早的。这样会形成森林的结构。显然,一个点只会对它的祖先产生贡献。而它对某个祖先\(v\)产生贡献的冲要条件就是在它到\(v\)的路径上没有比\(v\)更早的操作。

求这个森林可以使用扫描线。按\(y\)从上往下扫描,每加入一个操作就删去在它前面的出现时间晚于它的操作。这可以用set来维护。

剩下的部分可以按时间从前往后枚举所有操作,每次答案就是它的子树和,然后切断它与父亲的边。方便起见,可以用时间倒流的技巧,就相当与每次合并一个点和它的父亲。用并查集维护即可。

时间复杂度\(O(n \log n)\)。

#include <bits/stdc++.h>
using namespace std;
#define gc() getchar()
template <typename tp>
inline void read(tp& x) {
x = 0; char tmp; bool key = 0;
for (tmp = gc() ; !isdigit(tmp) ; tmp = gc())
key = (tmp == '-');
for ( ; isdigit(tmp) ; tmp = gc())
x = (x << 3) + (x << 1) + (tmp ^ '0');
if (key) x = -x;
}
const int N = 300010, INF = 0x3f3f3f3f;
struct edge {
int la,b;
} con[N << 1];
int tot,fir[N << 1];
void add(int from,int to) {
con[++tot] = (edge) {fir[from],to};
fir[from] = tot;
}
struct data {
int x,y,v;
bool operator < (const data& a) const {
return y > a.y;
}
} dat[N << 1];
int n,m,cnt,fa[N],val[N],uni[N],ans[N];
int getfa(int pos) {
return pos == uni[pos] ? pos : uni[pos] = getfa(uni[pos]);
}
typedef pair<int,int> pii;
set<pii> st;
set<pii> :: iterator t, t1;
void ins(int x,int y) {
t = st.insert(pii(x,y)).first;
while (t != st.begin()) {
t1 = t;
-- t1;
if (t1 -> second < y) break;
st.erase(t1);
}
}
int ask(int p) {
return st.upper_bound(pii(p+1,0))->second;
}
int main() {
read(n);
for (int i = 1, x, y ; i <= n ; ++ i) {
read(x), read(y);
-- x, -- y;
dat[++cnt] = (data) {x,y,0};
}
read(m);
for (int i = 1, x, y ; i <= m ; ++ i) {
read(x), read(y);
dat[++cnt] = (data) {x,y,i};
}
dat[++cnt] = (data) {INF,INF,m+1};
sort(dat+1,dat+cnt+1);
for (int i = 1, las = 1, tmp ; i <= cnt ; ++ i) {
if (dat[i].y != dat[las].y) {
for (int j = las ; j < i ; ++ j)
if (dat[j].v) ins(dat[j].x, dat[j].v);
las = i;
}
tmp = ask(dat[i].x);
if (dat[i].v) fa[dat[i].v] = tmp;
else ++ val[tmp];
}
for (int i = 1 ; i <= m ; ++ i)
uni[i] = i;
for (int i = m ; i >= 1 ; -- i) {
ans[i] = val[getfa(i)];
uni[getfa(i)] = getfa(fa[i]);
val[getfa(fa[i])] += ans[i];
}
for (int i = 1 ; i <= m ; ++ i)
printf("%d\n",ans[i]);
return 0;
}

小结:这是一道技巧性比较强的数据结构题。利用询问间的关系解题的思路,还是有启发意义的。

【做题】CERC2017B. Buffalo Barricades——时间倒流的更多相关文章

  1. LCT做题笔记

    最近几天打算认真复习LCT,毕竟以前只会板子.正好也可以学点新的用法,这里就用来写做题笔记吧.这个分类比较混乱,主要看感觉,不一定对: 维护森林的LCT 就是最普通,最一般那种的LCT啦.这类题目往往 ...

  2. ACM 做题过程中的一些小技巧。

    ACM做题过程中的一些小技巧. 1.一般用C语言节约空间,要用C++库函数或STL时才用C++; cout.cin和printf.scanf最好不要混用. 2.有时候int型不够用,可以用long l ...

  3. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

  4. SDOI2014 R1做题笔记

    SDOI2014 R1做题笔记 经过很久很久的时间,shzr又做完了SDOI2014一轮的题目. 但是我不想写做题笔记(

  5. SDOI2016 R1做题笔记

    SDOI2016 R1做题笔记 经过很久很久的时间,shzr终于做完了SDOI2016一轮的题目. 其实没想到竟然是2016年的题目先做完,因为14年的六个题很早就做了四个了,但是后两个有点开不动.. ...

  6. 【做题】spoj4060 A game with probability——dp

    赛前做题时忽然发现自己概率博弈类dp很弱,心好慌.(获胜概率或最优解期望) 于是就做了这道题,续了特别久. 一开始列dp式子的时候就花了很长时间,首先搞错了两次,然后忘记了根据上一轮dp值直接确定选什 ...

  7. noip做题记录+挑战一句话题解?

    因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...

  8. 小学生轻松做题App

    作业链接:https://edu.cnblogs.com/campus/fzzcxy/2016SE/homework/2180 原型模型设计工具:墨刀 原型模型链接:https://modao.cc/ ...

  9. BZOJ做题记录[0512~?]

    觉得做一道开一篇真不好...好多想找的东西都被刷下去了... 至于?的日期究竟到什么时候...还是看心情...但是估计不会超过七天吧 最后更新时间:05/19 10:42 [05/14 10:56]我 ...

随机推荐

  1. SM3杂凑算法Python语言实现——第三部分

    SM3杂凑算法实现--第三部分 一.SM3 密码概述        我们首先把需要用到的算法呈现出来,最后我们再考虑如何集合为一个库的方法,这一部分我们就开始编写一个新的算法:国家商用密码标准SM3密 ...

  2. linux安装elk

    环境: centOS7 JDK8 Elasticsearch-6.6.1 Logstash-6.6.1 Kibana-6.6.1 准备: jdk下载地址:https://www.oracle.com/ ...

  3. python学习笔记5-字典

    # 字典(哈希映射.关联数组) d0 = {'a': 2, [0,1]:[1,2,3]} # TypeError: unhashable type: 'list' # 值可以是任意数据类型,但键不能是 ...

  4. XLSReadWriteII5导入excel数据

    procedure TForm1.Button1Click(Sender: TObject); var xls: TXLSReadWriteII5; openFile: TOpenDialog; Ro ...

  5. Asp.net MVC WebApi项目的自动接口文档及测试功能打开方法

    https://blog.csdn.net/foren_whb/article/details/78866133

  6. [js]d3.js绘制拓扑树

    echart也支持拓扑树了 所需的json数据格式: children嵌套 vis.js也支持绘制拓扑树 数据格式: nodes: {id, label, title} edges: {from, t ...

  7. principal(括号匹配+多组查询)

    题目传送门: 把所有括号相匹配的段直接预处理出来就行了 #include <bits/stdc++.h> using namespace std; #define ll long long ...

  8. js获取 gif 的帧数

    使用 javascript 获取 GIF 图的帧数,如果帧数过大,则不让传到服务器 这里是使用一个插件: github地址为: https://github.com/buzzfeed/libgif-j ...

  9. selenium各种定位方法(转)

    selenium使用 Xpath CSS JavaScript jQuery的定位方法 (治疗selenium各种定位不到,点击不了的并发症) 2017年07月28日 22:47:36 阅读数:369 ...

  10. notify.min.js

    /*! * @wcjiang/notify v2.0.11 * JS achieve the browser title flashing , scrolling, voice prompts , c ...