这是一道环上的问题,我们先将一个环展开,再复制一次。

这样,任何一个合法方案一定对应在转换后的序列的一些连续的区间,使得它们的并的长度大于等于圈长。

然后,我们将区间合并一下(就是将一些被其他区间包含的区间去掉)。

假设某个答案的区间是r1,r2,r3,...rk,我们可以让ri为"与ri-1连接的右端点最靠右的区间“,明显这样不会不原来的答案劣。

所以,一旦确定了起点,那么在该起点的情况下最优的覆盖圆环的方案就确定了,确定了区间,我们可以用倍增的思想来判断一串连续区间覆盖len最少需要多少个,(有点像跳跃式的LCA求法中用倍增的思想)。这个O(logn)可搞,然后枚举起点是O(n),总的复杂度是O(nlogn)。

/**************************************************************
Problem: 1780
User: idy002
Language: C++
Result: Accepted
Time:2124 ms
Memory:33796 kb
****************************************************************/ #include <cstdio>
#include <vector>
#include <algorithm>
#define fprintf(...)
#define maxn 200010
#define maxp 18
using namespace std; struct Rng {
int lf, rg;
Rng(){}
Rng( int lf, int rg ):lf(lf),rg(rg){}
bool operator<( const Rng &b ) const { return lf<b.lf || (lf==b.lf&&rg>b.rg); }
}; int len, n;
Rng rng[maxn]; int tot;
vector<int> stk;
bool mark[maxn];
int nxt[maxn][maxp+], dis[maxn][maxp+]; int main() {
scanf( "%d%d", &len, &n );
for( int i=,lf,ln; i<=n; i++ ) {
scanf( "%d%d", &lf, &ln );
rng[++tot] = Rng(lf,lf+ln);
}
for( int i=,otot=tot; i<=otot; i++ )
rng[++tot] = Rng( rng[i].lf+len, rng[i].rg+len );
sort( rng+, rng++tot );
for( int i=; i<=tot; i++ )
if( !mark[i] ) {
stk.push_back( i );
fprintf( stderr, "Got [%d,%d]\n", rng[i].lf, rng[i].rg );
for( int j=i+; j<=tot; j++ )
if( rng[j].rg<=rng[i].rg ) mark[j]=true;
else break;
}
for( int t=; t<stk.size(); t++ ) {
int u=stk[t];
nxt[u][] = u;
dis[u][] = ;
for( int tt=t+; tt<stk.size(); tt++ ) {
int v=stk[tt];
if( rng[v].lf<=rng[u].rg ) {
nxt[u][] = v;
dis[u][] = rng[v].rg-rng[u].rg;
} else break;
}
}
for( int p=; p<=maxp; p++ )
for( int t=; t<stk.size(); t++ ) {
int u=stk[t];
nxt[u][p] = nxt[nxt[u][p-]][p-];
dis[u][p] = dis[u][p-]+dis[nxt[u][p-]][p-];
}
/*
for( int t=0; t<stk.size(); t++ ) {
int u=stk[t];
fprintf( stderr, "from [%d,%d]: \n", rng[u].lf, rng[u].rg );
for( int p=0; p<=5; p++ )
fprintf( stderr, "nxt[%d]=[%d,%d] dis[%d]=%d\n", p, rng[nxt[u][p]].lf, rng[nxt[u][p]].rg, p, dis[u][p] );
fprintf( stderr, "\n" );
}
*/
int ans=n;
for( int t=; t<stk.size(); t++ ) {
int u=stk[t];
int remain=len-(rng[u].rg-rng[u].lf);
int tans = ;
for( int p=maxp; dis[u][] && dis[u][]<remain; p-- )
if( dis[u][p]<remain ) {
remain-=dis[u][p];
tans += <<p;
u=nxt[u][p];
}
tans++;
if( dis[u][]== ) continue;
fprintf( stderr, "from [%d,%d] got ans %d\n", rng[u].lf, rng[u].rg, tans );
if( tans<ans ) ans=tans;
}
printf( "%d\n", ans );
}

bzoj 1780的更多相关文章

  1. bzoj usaco 金组水题题解(2.5)

    bzoj 2197: [Usaco2011 Mar]Tree Decoration 树形dp..f[i]表示处理完以i为根的子树的最小时间. 因为一个点上可以挂无数个,所以在点i上挂东西的单位花费就是 ...

  2. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  3. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  4. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  5. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  6. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  7. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

  8. 【清华集训】楼房重建 BZOJ 2957

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  9. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

随机推荐

  1. 9 - Python函数定义-位置参数-返回值

    目录 1 函数介绍 1.1 为什么要使用函数 1.2 Python中的函数 2 函数的基本使用 3 函数的参数 3.1 参数的默认值 3.2 可变参数 3.2.1 可变位置传参 3.2.2 可变关键字 ...

  2. docker之设置开机自启动(二)

    docker的自启动 通过sysv-rc-conf等管理 启动脚本 # docker.service #!/bin/sh sudo systemctl enable docker sudo syste ...

  3. selenium滚动到顶部与底部

    #coding=utf-8 from selenium import webdriver #滚动到浏览器顶部 js_top = "var q=document.documentElement ...

  4. 提高spring boot jpa性能(译)

    Spring Data JPA为Spring应用程序提供了数据访问层的实现.这是一个非常方便的组件,因为它不会重新发明每个新应用程序的数据访问方式,因此您可以花更多时间来实现业务逻辑.使用Spring ...

  5. Denoise Autoencoder简单理解

    自编码器通过学习隐含特征来表达原始数据,那什么是denoise autoencoder呢? 关于Autoencoder参考:http://blog.csdn.net/on2way/article/de ...

  6. jquery.query.js 插件(示例及简单应用) —— html之间传值

    帮助文档 var url = location.search; > "?action=view&section=info&id=123&debug&te ...

  7. **[权限控制] 利用CI钩子实现权限认证

    http://codeigniter.org.cn/forums/thread-10877-1-1.html 一直没找到CI的权限认证扩展,以前好像找到过一个老外的扩展,不过不怎么好用,现在记不清了, ...

  8. 【转】servlet/filter/listener/interceptor区别与联系

    原文:https://www.cnblogs.com/doit8791/p/4209442.html 一.概念: 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台 ...

  9. IEEEXtreme 10.0 - Mancala'h

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - Mancala'h 题目来源 第10届IEEE极限编程大赛 https://www.hackerrank.c ...

  10. 实现手机端上下左右滑屏的jq原生代码和使用库·两种办法

    先来一个原生的.我使用的是jq. 需要注意的地方就是被触发的元素最好不要是body,这个代码也可以修改,如果obj传进来的是body那么,$(this)必须是你的监听元素,不然会冒泡泡,整个项目就…… ...