洛谷P1712 区间
题意:给你n个区间,从中选择m个,使得它们有交,且最长与最短区间的差值最小。
解:这道题我想了好多
的,nlog²n错的,nlogn错的,最后终于想出nlogn的了......
把区间按照长度排序,然后依次在线段树上加。
如果某一次等于m了,那么一个一个删,删到小于m的时候,更新答案。
证明:那些之前的区间如果想要成为答案,那么必须是和比当前这个还靠前的区间来组成。
这样的话当到这一个时,之前的要么被计算,要么不会更优。故可以删掉。
#include <cstdio>
#include <algorithm> const int N = , INF = 0x3f3f3f3f; int sum[N << ], large[N << ], tag[N << ], X[N << ]; struct ITV {
int r, l, len;
inline bool operator <(const ITV &w) const {
return len < w.len;
}
}a[N]; inline void pushup(int o) {
int ls = o << ;
int rs = ls | ;
sum[o] = sum[ls] + sum[rs];
large[o] = std::max(large[ls], large[rs]);
return;
} inline void pushdown(int l, int r, int o) {
if(tag[o]) {
int ls = o << ;
int rs = ls | ;
int mid = (l + r) >> ;
tag[ls] += tag[o];
tag[rs] += tag[o];
sum[ls] += (mid - l + ) * tag[o];
sum[rs] += (r - mid) * tag[o];
large[ls] += tag[o];
large[rs] += tag[o];
tag[o] = ;
}
return;
} inline void add(int L, int R, int v, int l, int r, int o) {
if(L <= l && r <= R) {
tag[o] += v;
sum[o] += v * (r - l + );
large[o] += v;
return;
}
pushdown(l, r, o);
int mid = (l + r) >> ;
if(L <= mid) {
add(L, R, v, l, mid, o << );
}
if(mid < R) {
add(L, R, v, mid + , r, o << | );
}
pushup(o);
return;
} int main() { int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d%d", &a[i].l, &a[i].r);
a[i].len = a[i].r - a[i].l;
X[i << ] = a[i].l;
X[(i << ) - ] = a[i].r;
}
std::sort(a + , a + n + );
std::sort(X + , X + (n << ) + );
int t = std::unique(X + , X + (n << ) + ) - X - ;
int j = , ans = INF;
for(int i = ; i <= n; i++) {
a[i].l = std::lower_bound(X + , X + t + , a[i].l) - X;
a[i].r = std::lower_bound(X + , X + t + , a[i].r) - X;
add(a[i].l, a[i].r, , , t, );
while(large[] >= m) {
add(a[j].l, a[j].r, -, , t, );
//printf("large[1] = %d ans = %d \n i = %d j = %d \n", large[1], ans, i, j);
ans = std::min(ans, a[i].len - a[j].len);
j++;
}
}
if(ans == INF) {
ans = -;
}
printf("%d\n", ans);
return ;
}
AC代码
这个sum其实是不必要的。
然后我还用动态开点写了一发......被卡空间了。
#include <cstdio>
#include <algorithm> const int N = , INF = 0x3f3f3f3f; int large[N * ], tag[N * ], root, ls[N * ], rs[N * ], tot; struct ITV {
int r, l, len;
inline bool operator <(const ITV &w) const {
return len < w.len;
}
}a[N]; inline void pushup(int o) {
large[o] = std::max(large[ls[o]], large[rs[o]]);
return;
} inline void pushdown(int l, int r, int o) {
if(tag[o]) {
int mid = (l + r) >> ;
if(ls[o]) {
large[ls[o]] += tag[o];
tag[ls[o]] += tag[o];
}
if(rs[o]) {
large[rs[o]] += tag[o];
tag[rs[o]] += tag[o];
}
tag[o] = ;
}
return;
} inline void add(int L, int R, int v, int l, int r, int &o) {
if(!o) {
o = ++tot;
}
if(L <= l && r <= R) {
tag[o] += v;
large[o] += v;
return;
}
if(!ls[o]) {
ls[o] = ++tot;
}
if(!rs[o]) {
rs[o] = ++tot;
}
pushdown(l, r, o);
int mid = (l + r) >> ;
if(L <= mid) {
add(L, R, v, l, mid, ls[o]);
}
if(mid < R) {
add(L, R, v, mid + , r, rs[o]);
}
pushup(o);
return;
} int main() { int n, m, lm = ;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%d%d", &a[i].l, &a[i].r);
a[i].len = a[i].r - a[i].l;
lm = std::max(lm, a[i].r);
}
std::sort(a + , a + n + );
int j = , ans = INF;
for(int i = ; i <= n; i++) {
add(a[i].l, a[i].r, , , lm, root);
while(large[] >= m) {
add(a[j].l, a[j].r, -, , lm, root);
//printf("large[1] = %d ans = %d \n i = %d j = %d \n", large[1], ans, i, j);
ans = std::min(ans, a[i].len - a[j].len);
j++;
}
}
if(ans == INF) {
ans = -;
}
printf("%d\n", ans);
return ;
}
95分动态开点
洛谷P1712 区间的更多相关文章
- 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化
洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...
- [Noi2016]区间 BZOJ4653 洛谷P1712 Loj#2086
额... 首先,看到这道题,第一想法就是二分答案+线段树... 兴高采烈的认为我一定能AC,之后发现n是500000... nlog^2=80%,亲测可过... 由于答案是求满足题意的最大长度-最小长 ...
- 【洛谷 P1712】 [NOI2016]区间 (线段树+尺取)
题目链接 emmm看起来好像无从下手, \(l_i,r_i\)这么大,肯定是要离散化的. 然后我们是选\(m\)个区间,我们先对这些区间按长度排个序也不影响. 排序后,设我们取的\(m\)个区间的编号 ...
- 洛谷 P1712 [NOI2016]区间(线段树)
传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次 ...
- [洛谷P1712] NOI2016 区间
问题描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...
- 洛谷$P1712\ [NOI2016]$区间 线段树
正解:线段树 解题报告: 传送门$QwQ$ $umm$很久以前做的了来补个题解$QwQ$ 考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权 ...
- 洛谷——P2082 区间覆盖(加强版)
P2082 区间覆盖(加强版) 题目描述 已知有N个区间,每个区间的范围是[si,ti],请求出区间覆盖后的总长. 输入输出格式 输入格式: N s1 t1 s2 t2 …… sn tn 输出格式: ...
- 洛谷P2082 区间覆盖(加强版)(珂朵莉树)
传送门 虽然是黄题而且还是一波离散就能解决的东西 然而珂朵莉树还是很好用 相当于一开始区间全为0,然后每一次区间赋值,问最后总权值 珂朵莉树搞一搞就好了 //minamoto #include< ...
- 洛谷1063 +区间dp(经典问题)
题目网址:https://www.luogu.com.cn/problem/P1063 题意大致是:给定一个序列An,第i个元组表示为(Ai,Ai+1),序列位置不变,当合并一个区间[l,l+1]时开 ...
随机推荐
- hive排序
1.升序排序 hive > select id,name,sal from emp order by sal; 2.降序 添加关键字desc hive > select id,nam ...
- tensorflow实现基于LSTM的文本分类方法
tensorflow实现基于LSTM的文本分类方法 作者:u010223750 引言 学习一段时间的tensor flow之后,想找个项目试试手,然后想起了之前在看Theano教程中的一个文本分类的实 ...
- python爬虫之git的使用(github的使用)
上面博文中我们简单的了解了一下基本的git操作,但是我们都是将代码放到了本地的仓库里面,但是如果我们是一个团队开发的话,肯定不会放到每个人的本地,必须得有个统一的地方存放代码,国外的大家都在使用git ...
- 老男孩python学习自修第二十三天【多线程】
1. 线程的创建与运行 #!/usr/bin/env python # _*_ coding:UTF-8 _*_ from threading import Thread def foo(param1 ...
- supervisor /var/run/supervisor/supervisor.sock not found 或者/tmp/supervisor.sock not found
刚按装完supervisor,这时候用supervisorctr -c supervisor.conf 会报错: /var/run/supervisor/supervisor.sock not fou ...
- vue計算屬性
計算屬性:computed 和method的差別:computed是基於它的依賴緩存,只有它的相關依賴發生改變時才會重新獲取值. method是在重新渲染時,函數總會重新調用. comuputed:默 ...
- CSS 的三种样式 内联 内部 外部
CSS:层叠样式表的缩写 就是 Cascading Style Sheets Cascading Style Sheets : 层叠样式表 优先级问题 :遵守就近原则 内联> 内部>外部 ...
- Java多线程之单例模式(线程安全)
package org.study2.javabase.ThreadsDemo.sync; /** * @Auther:GongXingRui * @Date:2018/9/20 * @Descrip ...
- react 入坑笔记(二) - State
React State 一. state 大致思想:在 react 中,每个组件都是一个状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致.React 里,只需更新组件的 ...
- ImportError: No module named google.protobuf.internal
下载: protobuf-3.3.0 设置路径:export PYTHONPATH=/gruntdata/lihaiyang/local/protobuf-3.3.0/python:$PYTHONPA ...