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

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

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

假设某个答案的区间是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. 59、有用过with statement吗?它的好处是什么?

    python中的with语句是用来干嘛的?有什么作用? with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种 用法举例如下: with open('output.txt', 'w ...

  2. escapeRegExp捕捉通配符的代码解析

    费了好几个小时,把一小段正则代码搞通了,回顾并记下,加深记忆. 该段代码来自yii.js,它也是引自stackoverflow,地址是:http://stackoverflow.com/questio ...

  3. Python3中对Dict的内存优化

    众所周知,python3.6这个版本对dict的实现是做了较大优化的,特别是在内存使用率方面,因此我觉得有必要研究一下最新的dict的源码实现. 前后断断续续看了大概一周多一点,主要在研究dict和创 ...

  4. UVA题解三

    UVA题解三 UVA 127 题目描述:\(52\)张扑克牌排成一列,如果一张牌的花色或者数字与左边第一列的最上面的牌相同,则将这张牌移到左边第一列的最上面,如果一张牌的花色或者数字与左边第三列的最上 ...

  5. ORACLE数据库导出导入数据

    准备工作: 1.登录管理员system 2.create directory dbdata as 'C:\oracle\tempData';--创建备份文件夹 3.grant read,write o ...

  6. Spring之IOC,DI,动态代理,反射

    Spring框架是J2EE开发中一个使用广泛的框架,它使得dao和service层的维护更加便利.Spring框架有两个重要的特征,一个是IOC,另一个是AOP.我们在这里主要介绍IOC,以及IOC中 ...

  7. JNDI(Java Naming and Directory Interface,Java命名和目录接口)

    JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访 ...

  8. Codeforces 351D Jeff and Removing Periods(莫队+区间等差数列更新)

    题目链接:http://codeforces.com/problemset/problem/351/D 题目大意:有n个数,每次可以删除掉数值相同并且所在位置成等差数列的数(只删2个数或者只删1个数应 ...

  9. python 函数操作

    四.函数 定义: #!/usr/local/env python3 ''' Author:@南非波波 Blog:http://www.cnblogs.com/songqingbo/ E-mail:qi ...

  10. 【笔试题】Java 中如何递归显示一个目录下面的所有目录和文件?

    笔试题 Java 中如何递归显示一个目录下面的所有目录和文件? import java.io.File; public class Test { private static void showDir ...