https://www.lydsy.com/JudgeOnline/problem.php?id=4653

首先很容易想到离散之后排序,用线段树或者树状数组去维护。

问题在于按照什么排序,如果按照左端点右端点排序,线段树就需要维护最大值最小值和区间和等等信息,在区间和超过M之后最大值就变为了K大到最大的信息,不但麻烦而且难以下手。

所以想到直接按照区间长度排序,仅仅维护一个区间最值,代表这个区间里最大的点被覆盖了多少次,然后用一种尺取的思想,使得线段树里的最大值一值不超过M,如果超过了就在尾部开始删除直到M以下,与此同时更新最大值。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 5e5 + ;
const int maxm = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int Hash[maxn * ];
int len[maxn];
PII line[maxn];
struct Tree{
int l,r,lazy,Max;
}tree[maxn << ];
void Build(int t,int l,int r){
tree[t].l = l; tree[t].r = r;
tree[t].lazy = tree[t].Max = ;
if(l == r) return;
int m = (l + r) >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
}
void Pushdown(int t){
if(tree[t].lazy){
tree[t << ].lazy += tree[t].lazy;
tree[t << | ].lazy += tree[t].lazy;
tree[t << ].Max += tree[t].lazy;
tree[t << | ].Max += tree[t].lazy;
tree[t].lazy = ;
}
}
void Pushup(int t){
tree[t].Max = max(tree[t << ].Max,tree[t << | ].Max);
}
void update(int t,int l,int r,int w){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].Max += w;
tree[t].lazy += w;
return;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) update(t << ,l,r,w);
else if(l > m) update(t << | ,l,r,w);
else{
update(t << ,l,m,w); update(t << | ,m + ,r,w);
}
Pushup(t);
}
bool cmp(PII a,PII b){
return a.se - a.fi < b.se - b.fi;
}
int main(){
Sca2(N,M);
int cnt = ;
for(int i = ; i <= N; i ++){
line[i].fi = read(); line[i].se = read();
Hash[++cnt] = line[i].fi; Hash[++cnt] = line[i].se;
}
sort(Hash + ,Hash + + cnt);
sort(line + ,line + + N,cmp);
cnt = unique(Hash + ,Hash + + cnt) - Hash - ;
for(int i = ; i <= N ; i ++){
len[i] = line[i].se - line[i].fi;
line[i].fi = lower_bound(Hash + ,Hash + + cnt,line[i].fi) - Hash;
line[i].se = lower_bound(Hash + ,Hash + + cnt,line[i].se) - Hash;
}
Build(,,cnt);
int tail = ;
int ans = INF;
for(int i = ; i <= N ; i ++){
update(,line[i].fi,line[i].se,);
while(tree[].Max >= M){
ans = min(ans,len[i] - len[tail]);
update(,line[tail].fi,line[tail].se,-);
tail++;
}
}
if(ans == INF) ans = -;
Pri(ans);
return ;
}

BZOJ4653 尺取法 + 线段树的更多相关文章

  1. luogu1712 区间 (尺取法+线段树)

    先把区间按照长度从小到大排序,然后用尺取法来做 大概就是先一点一点把区间算上 直到某个点被覆盖了m次,然后一点一点把最前面的区间扔掉,直到没有点被覆盖m次,这样反复做(相当于是它选择的区间左右端点在那 ...

  2. codeforces 652C C. Foe Pairs(尺取法+线段树查询一个区间覆盖线段)

    题目链接: C. Foe Pairs time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  3. luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分

    LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...

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

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

  5. BZOJ4653 [NOI2016]区间 [线段树,离散化]

    题目传送门 区间 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就 ...

  6. 【BZOJ-4653】区间 线段树 + 排序 + 离散化

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 107  Solved: 70[Submit][Status][Di ...

  7. BZOJ4653: [Noi2016]区间(线段树 双指针)

    题意 题目链接 Sol 按照dls的说法,一般这一类的题有两种思路,一种是枚举一个点\(M\),然后check它能否成为答案.但是对于此题来说好像不好搞 另一种思路是枚举最小的区间长度是多少,这样我们 ...

  8. BZOJ4653:[NOI2016]区间(线段树)

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

  9. 2018.08.17 bzoj4653: [Noi2016]区间(线段树+尺取法)

    传送门 将坐标离散化之后直接用尺取法(双指针)+线段树维护. 其实就是说只要目前所有点的被覆盖次数是大于等于m的就移动左指针删除区间更新答案,否则移动右指针加入区间更新答案. 话说忘记排序以及建树的时 ...

随机推荐

  1. Ubuntu 16.04配置Java Web开发环境

    说明:在Linux下无论是开发还是服务器配置,我个人建议都安装二进制包版本的,优点:配置清晰,容易发现问题,性能调优方便等.缺点:配置太复杂.而其余平台的建议是一键安装版本,毕竟都是用于测试的,不会实 ...

  2. Kibana-4.6.6 marvel插件license过期重新注册

    1.注册新的license,https://register.elastic.co/marvel_register,注册完毕邮箱收取下载地址,将新的license下载到本地 2.到license所在目 ...

  3. POJ 3020 -Antenna Placement-二分图匹配

    题意:一个N*M的矩阵里有K个观测点,你必须放置天线覆盖所有观测点.每个雷达只能天线两个观测点,这两点必须相邻.计算最少天线数. 做法:将所有相邻的观测点连起来,建图.跑一遍匈牙利算法就计算出了最大的 ...

  4. Django+Xadmin打造在线教育系统(九)

    xadmin的进阶开发 因版本问题.有些配置可能无效 自定义icon xadmin的图标采用的是第三方css样式font awesome,我们可以进官网下载最新的样式替代原本的,下载地址:http:/ ...

  5. web 压力测试工具

    最近有收到任务,测试新服务器的性能. 花了很长时间做搜索,也整理了一些资料.以下是收集到一些简单易用的分析工具.推荐给大家使用. WebBenchhttp://www.ha97.com/4623.ht ...

  6. 自学华为IoT物联网_01 物联网概述

    点击返回自学华为IoT物流网 自学华为IoT物联网_01 物联网概述 1. 物联网的概念 百度百科: 物联网(Internet of Things),国内外普遍公认的是MIT Auto-ID中心Ash ...

  7. 【HDU3032】Nim or not Nim?(博弈论)

    [HDU3032]Nim or not Nim?(博弈论) 题面 HDU 题解 \(Multi-SG\)模板题 #include<iostream> #include<cstdio& ...

  8. 【CF734F】Anton and School(构造)

    [CF734F]Anton and School(构造) 题面 Codeforces 洛谷 题解 算是一道\(easy\)? 发现\((a\&b)+(a|b)=a+b\). 那么根据给定条件我 ...

  9. 【BZOJ5315】[JSOI2018]防御网络(动态规划,仙人掌)

    [BZOJ5315][JSOI2018]防御网络(动态规划,仙人掌) 题面 BZOJ 洛谷 题解 显然图是仙人掌. 题目给了斯坦纳树就肯定不是斯坦纳树了,,,, 总不可能真让你\(2^n\)枚举点集再 ...

  10. cf1076E Vasya and a Tree (线段树)

    我的做法: 给询问按$deep[v]+d$排序,每次做到某一深度的时候,先给这个深度所有点的值清0,然后直接改v的子树 官方做法比较妙妙: dfs,进入v的时候给$[deep[v],deep[v]+d ...