题目链接:戳我

60分部分分还是很好拿的,排序(按照左端点为第一关键字,右端点为第二关键字)之后一个\(O(n^2)\),暴力判交,更新最小值,就可以水过前12个测试点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define MAXN 100010
#define inf 0x3f3f3f3f
using namespace std;
int n,m,ans=inf;
struct Node{int l,r;}node[MAXN];
inline bool cmp(struct Node x,struct Node y)
{
if(x.l==y.l) return x.r<y.r;
return x.l<y.l;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].l,&node[i].r);
if(node[i].l==node[i].r) i--,n--;
}
sort(&node[1],&node[n+1],cmp);
for(int i=1;i<=n;i++)
{
vector<int>v;
int cnt=1;
v.push_back(node[i].r-node[i].l);
for(int j=1;j<=n;j++)
{
if(node[j].r<node[i].r||j==i||node[j].l>=node[i].r) continue;
v.push_back(node[j].r-node[j].l);
cnt++;
}
if(cnt<m) continue;
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++)
{
int j=i+m-1;
if(j>=v.size()) break;
ans=min(ans,v[j]-v[i]);
}
}
if(ans==inf) printf("-1\n");
else printf("%d\n",ans);
return 0;
}

现在我们来考虑正解——

区间1e9有点大,先离散化一下。

然后我们按照长度从小到大排序qwq,保证一个单调性,然后使用尺取法。给当前枚举到的线段所指区间+1,用线段树维护全局最大值,如果最大值==m,就可以用右指针所指线段的长度-左指针所指线段的长度更新答案了。如果当前全局最大值大于m,我们可以弹出原先的线段。

什么是尺取法?就是维护两个指针一样的东西( l,r) ,每次确定区间的左端点,让\(r\)不断向右移动,直到满足条件停下,维护一下答案,直到\(r>n\) ]

不过,注意一下,不要把node[i].l==node[i].r,省略掉qwqwq(不然会WA在UOJ上)

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 500010
#define INF 2147483647
using namespace std; int n,m,ans=INF,cnt;
int pre[MAXN<<1];
struct Node{int maxx,tag;}t[MAXN<<4];
struct Node2{int l,r,len,id;}node[MAXN<<1]; inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;} inline void push_up(int x){t[x].maxx=max(t[ls(x)].maxx,t[rs(x)].maxx);} inline bool cmp(struct Node2 x,struct Node2 y){return x.len<y.len;} inline void solve(int x,int k)
{
t[x].maxx+=k;
t[x].tag+=k;
} inline void push_down(int x)
{
if(t[x].tag)
{
solve(ls(x),t[x].tag);
solve(rs(x),t[x].tag);
t[x].tag=0;
}
} inline void update(int x,int l,int r,int ll,int rr,int k)
{
if(ll<=l&&r<=rr) {solve(x,k);return;}
int mid=(l+r)>>1;
push_down(x);
if(ll<=mid) update(ls(x),l,mid,ll,rr,k);
if(mid<rr) update(rs(x),mid+1,r,ll,rr,k);
push_up(x);
} int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&node[i].l,&node[i].r);
node[i].len=node[i].r-node[i].l;
node[i].id=i;
}
for(int i=1;i<=n;i++) pre[++cnt]=node[i].l,pre[++cnt]=node[i].r;
sort(&pre[1],&pre[cnt+1]);
cnt=unique(&pre[1],&pre[1+cnt])-pre-1;
for(int i=1;i<=n;i++)
{
node[i].l=lower_bound(&pre[1],&pre[cnt+1],node[i].l)-pre;
node[i].r=lower_bound(&pre[1],&pre[cnt+1],node[i].r)-pre;
}
sort(&node[1],&node[1+n],cmp);
int head=0,tail=0;
for(;;)
{
while(tail<n&&t[1].maxx<m)
{
++tail;
update(1,1,cnt,node[tail].l,node[tail].r,1);
}
if(t[1].maxx<m) break;
while(head<n&&t[1].maxx>=m)
{
++head;
update(1,1,cnt,node[head].l,node[head].r,-1);
}
ans=min(ans,node[tail].len-node[head].len);
}
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
return 0;
}

注意这种离散化的题目!!!线段树要开8倍qwqwq

要不然会RE掉三个点qwqwq

NOI2009 区间的更多相关文章

  1. NOI2009 二叉查找树 【区间dp】

    [NOI2009]二叉查找树 [问题描述] 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左子树结点的数据值大,而比它右子树结点的数据值小.另一方面,这棵查找树中每个结点都有 ...

  2. bzoj 1564 [NOI2009]二叉查找树 区间DP

    [NOI2009]二叉查找树 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 906  Solved: 630[Submit][Status][Discu ...

  3. BZOJ1564 NOI2009二叉查找树(区间dp)

    首先按数据值排序,那么连续一段区间的dfs序一定也是连续的. 将权值离散化,设f[i][j][k]为i到j区间内所有点的权值都>=k的最小代价,转移时枚举根考虑是否修改权值即可. #includ ...

  4. [BZOJ1564][NOI2009]二叉查找树 树形dp 区间dp

    1564: [NOI2009]二叉查找树 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 879  Solved: 612[Submit][Status] ...

  5. 洛谷$P1864\ [NOI2009]$二叉查找树 区间$dp$

    正解:区间$dp$ 解题报告: 传送门$QwQ$ 首先根据二叉查找树的定义可知,数据确定了,这棵树的中序遍历就已经改变了,唯一能改变的就是通过改变权值从而改变结点的深度. 发现这里权值的值没有意义,所 ...

  6. [BZOJ1564][NOI2009]二叉查找树(区间DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1564 分析: 首先因为每个点的数据值不变,所以无论树的形态如何变,树的中序遍历肯定不变 ...

  7. 1563: [NOI2009]诗人小G

    1563: [NOI2009]诗人小G https://lydsy.com/JudgeOnline/problem.php?id=1563 分析: 直接转移f[i]=f[j]+cost(i,j),co ...

  8. 【BZOJ1564】【NOI2009】二叉查找树(动态规划)

    [BZOJ1564][NOI2009]二叉查找树(动态规划) 题面 BZOJ 洛谷 题目描述 已知一棵特殊的二叉查找树.根据定义,该二叉查找树中每个结点的数据值都比它左儿子结点的数据值大,而比它右儿子 ...

  9. BZOJ_1563_[NOI2009]诗人小G_决策单调性

    BZOJ_1563_[NOI2009]诗人小G_决策单调性 Description Input Output 对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度若最小的不协调度超 ...

随机推荐

  1. Rhythmk 学习 Hibernate 01 - maven 创建Hibernate 项目之 增删改查入门

    1.环境: Maven :3.1.1 开发工具:Spring Tool Suite 数据库 : Mysql  5.6 2.项目文件结构 文件代码: 2.1 .pom.xml <project x ...

  2. 想取得刚才nextval()的值时,放心大胆的用currval()吧,currval()的返回值并不会因为nextval()的并发访问而混乱

    以前写sql的时候总是担心current()得到的值并不会绝对等于我上一次nextval()取得的值;因为可能其他线程并发访问nextval(). 先说结论吧:当你拿到一个数据库连接,先nextval ...

  3. VS2010生成的文件在别的机器上运行提示“丢失MSVCR100D.dll”<转>

    用vs2010编写的程序经常会发生的一个问题.在自己的机器上运行的好好的,但是在别的机器上就会发生没有找到MSVCR100D.dll.这是 个很头疼的问题.对于一些代码量几百行的小程序,我不可能要求其 ...

  4. iOS 通过URL网络获取XML数据的两种方式

    转载于:http://blog.csdn.net/crayondeng/article/details/8738768 下面简单介绍如何通过url获取xml的两种方式. 第一种方式相对简单,使用NSD ...

  5. 机器学习算法中GBDT和XGBOOST的区别有哪些

    首先xgboost是Gradient Boosting的一种高效系统实现,并不是一种单一算法.xgboost里面的基学习器除了用tree(gbtree),也可用线性分类器(gblinear).而GBD ...

  6. python之private variable

    [python之private variable] Since there is a valid use-case for class-private members (namely to avoid ...

  7. Redis高可用及分片集群

    一.主从复制 使用异步复制 一个服务器可以有多个从服务器 从服务器也可以有自己的从服务器 复制功能不会阻塞主服务器 可以通过服务功能来上主服务器免于持久化操作,由从服务器去执行持久化操作即可. 以下是 ...

  8. zookeeper的ZAB协议

    ZAB协议概述 ZooKeeper并没有完全采用Paxos算法,而是使用了一种称为ZooKeeper Atomic Broadcast(ZAB,zookeeper原子消息广播协议)的协议作为其数据一致 ...

  9. [Training Video - 2] [Java Introduction] [Operator, Loops, Arrays, Functions]

    Operator : While Loop : For Loop :  Arrays : Code : public class FirstJavaClass { public static void ...

  10. Mac 安装GCC

    OS X上安装Homebrew和GCC的图文攻略 2016年08月31日 11:21:27 白马负金羁 阅读数:11380 标签: OS XGCCHomebrew 更多 个人分类: 应用技巧   版权 ...