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

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

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

假设某个答案的区间是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. 爬虫实战--使用Selenium模拟浏览器抓取淘宝商品美食信息

    from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exce ...

  2. 飘雪效果的swf

    //第一帧动作 import flash.events.Event; ;k<;k++) { var xuehua:xue= new xue(); xuehua.alpha = Math.rand ...

  3. 移动端测试===adb shell top命令解释

    adb shell top top命令提供了实时的对系统处理器的状态监视.它将显示系统中CPU最“敏感”的任务列表.该命令可以按CPU使用.内存使用和执行时间对任务进行排序. top 用法 >a ...

  4. Spring是什么+控制反转和依赖注入

    Spring是一个开源框架,是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 原因: (1)通过控制反转(IOC)达到松耦合,IOC也就是把控制权交出去,在使用中直接得到对象 (2)提 ...

  5. mac上卸载mysql

    在终端输入一下命令 sudo rm /usr/local/mysqlsudo rm -rf /usr/local/mysql*sudo rm -rf /Library/StartupItems/MyS ...

  6. [ python ] 进程的操作

    目录 (见右侧目录栏导航)- 1. 前言- 2. multiprocess模块- 2.1 multiprocess.Process模块    - 2.2 使用Process模块创建进程    - 2. ...

  7. C# Winform频繁刷新导致界面闪烁解决方法

    C#Winform频繁刷新导致界面闪烁解决方法 一.通过对窗体和控件使用双缓冲来减少图形闪烁(当绘制图片时出现闪烁时,使用双缓冲) 对于大多数应用程序,.NET Framework 提供的默认双缓冲将 ...

  8. JDK动态代理小例子

    一个小汽车,有一个跑run()的方法,我们想使用jdk动态代理使小汽车执行run之前 加点油,run之后洗车. 有四个类,接口Car(小汽车)Kayan(具体实现类(卡宴)) CarProxy(汽车的 ...

  9. php琐碎

    1.类中的常量,可以用类来引用: class MyClass() { const SUCCESS ="success"; const FAIL ="fail"; ...

  10. CSS初步了解

    CSS 概述 个人理解为对html的扩展,对html关键字进行功能添加. CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 样式通常存储在样式表 ...