题意:给你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 区间的更多相关文章

  1. 洛谷P1712 [NOI2016]区间 尺取法+线段树+离散化

    洛谷P1712 [NOI2016]区间 noi2016第一题(大概是签到题吧,可我还是不会) 链接在这里 题面可以看链接: 先看题意 这么大的l,r,先来个离散化 很容易,我们可以想到一个结论 假设一 ...

  2. [Noi2016]区间 BZOJ4653 洛谷P1712 Loj#2086

    额... 首先,看到这道题,第一想法就是二分答案+线段树... 兴高采烈的认为我一定能AC,之后发现n是500000... nlog^2=80%,亲测可过... 由于答案是求满足题意的最大长度-最小长 ...

  3. 【洛谷 P1712】 [NOI2016]区间 (线段树+尺取)

    题目链接 emmm看起来好像无从下手, \(l_i,r_i\)这么大,肯定是要离散化的. 然后我们是选\(m\)个区间,我们先对这些区间按长度排个序也不影响. 排序后,设我们取的\(m\)个区间的编号 ...

  4. 洛谷 P1712 [NOI2016]区间(线段树)

    传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次 ...

  5. [洛谷P1712] NOI2016 区间

    问题描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...

  6. 洛谷$P1712\ [NOI2016]$区间 线段树

    正解:线段树 解题报告: 传送门$QwQ$ $umm$很久以前做的了来补个题解$QwQ$ 考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权 ...

  7. 洛谷——P2082 区间覆盖(加强版)

    P2082 区间覆盖(加强版) 题目描述 已知有N个区间,每个区间的范围是[si,ti],请求出区间覆盖后的总长. 输入输出格式 输入格式: N s1 t1 s2 t2 …… sn tn 输出格式: ...

  8. 洛谷P2082 区间覆盖(加强版)(珂朵莉树)

    传送门 虽然是黄题而且还是一波离散就能解决的东西 然而珂朵莉树还是很好用 相当于一开始区间全为0,然后每一次区间赋值,问最后总权值 珂朵莉树搞一搞就好了 //minamoto #include< ...

  9. 洛谷1063 +区间dp(经典问题)

    题目网址:https://www.luogu.com.cn/problem/P1063 题意大致是:给定一个序列An,第i个元组表示为(Ai,Ai+1),序列位置不变,当合并一个区间[l,l+1]时开 ...

随机推荐

  1. AngularJS基于MVC的复杂操作案例

    AngularJS基于MVC的复杂操作案例 <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...

  2. javap -v没有显示LocalVaribleTable

    时隔多日,终于找到为什么javap -v .class文件没有LocalVariableTable出现 因为默认的javac编译没有生成相关的调试信息,这里我们可以通过javac -help查看指令帮 ...

  3. Flutter之 LimitedBox、Offstage、OverflowBox、SizedBox详解

    1. LimitedBox A box that limits its size only when it's unconstrained. 1.1 简介 LimitedBox,通过字面意思,也可以猜 ...

  4. redis设置防火墙的问题

    Linux 下载安装配置Redis完整步骤   安装: 1.获取redis资源 wget http://download.redis.io/releases/redis-4.0.8.tar.gz 2. ...

  5. idea的pom.xml中提示dependency‘’not found

    今天下午在更新svn上的项目到本地,发现pom文件中的如下依赖的version一直标红,鼠标放上去显示“dependency not found.” 同时检查了Maven Projects中该项目引入 ...

  6. linux上如何让other用户访问没有other权限的目录

    目前遇到一个问题,一个other用户要访问一个目录,他需要在这个目录下创建文件,因此这个目录需要一个写权限,于是就给了这个目录777的权限,这样这个权限有点太大了,很容易出现安全问题,那我们应该怎么办 ...

  7. spring 启动脚本分析

    参考:JVM 参数使用总结 参考:java  -Xms -Xmx -XX:PermSize -XX:MaxPermSize 参考:JVM调优总结 -Xms -Xmx -Xmn -Xss 参考:JAVA ...

  8. DAY07、字符编码和文件操作

    一.字符编码 1.什么是字符编码? 人类能识别的是字符等高级标识符,电脑只能识别0,1组成的标识符,要完成人与机器之间的信息交流,              一定需要一个媒介,进行两种标识符的转化(两 ...

  9. python数学第五天【常用概率分布】

    1. 概率基本公式 思考题: 3. 两点分布 4. 二项分布 推论一: 5.柏松分布 6. 均匀分布 7. 指数分布 8. 正态分布 9.常见分布的总结

  10. 如何调用layer.open打开的的iframe窗口中的JS