【BZOJ4444】[Scoi2015]国旗计划 双指针+倍增

摘要:
使用namespacestd;组分最大值=200010;组织=z;}}p[maxn<tot;intto[20][maxn<ans[maxn];chargc=getchar();gc=getchar();b) {returna.b<cmp);i++)to[j][i]=to[j-1][to[j-1][i]];=tot;b=0;=0;
【BZOJ4444】[Scoi2015]国旗计划

Description

A国正在开展一项伟大的计划——国旗计划。这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈。这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的边防战上作为这项计划的候选人。
A国幅员辽阔,边境线上设有M个边防站,顺时针编号1至M。每名边防战士常驻两个边防站,并且善于在这两个边防站之间长途奔袭,我们称这两个边防站之间的路程是这个边防战士的奔袭区间。n名边防战士都是精心挑选的,身体素质极佳,所以每名边防战士的奔袭区间都不会被其他边防战士的奔袭区间所包含。
现在,国十安全局局长希望知道,至少需要多少名边防战士,才能使得他们的奔袭区间覆盖全部的边境线,从而顺利地完成国旗计划。不仅如此,安全局局长还希望知道更详细的信息:对于每一名边防战士,在他必须参加国旗计划的前提下,至少需要多少名边防战士才能覆盖全部边境线,从而顺利地完成国旗计划。

Input

第1行,包含2个正整数N,M,分别表示边防战士数量和边防站数量。
随后n行,每行包含2个正整数。其中第i行包含的两个正整数Ci、Di分别表示i号边防战士常驻的两个边防站编号,Ci号边防站沿顺时针方向至Di号边防站力他的奔袭区间。数据保证整个边境线都是可被覆盖的。

Output

输出数据仅1行,需要包含n个正整数。其中,第j个正整数表示j号边防战士必须参加的前提下至少需要多少名边防战士才能顺利地完成国旗计划

Sample Input

4 8
2 5
4 7
6 1
7 3

Sample Output

3 3 4 3

HINT

 n≤2×10^5,M< 10^9,1≤Ci,Di≤M

题解:遇到环的题,显然要将环倍长一遍变成链做。

先排序,然后对于每个战士,他一定是传给他能传到的,右端点最远的战士,所以可以用双指针法搞定。

然后用倍增的思想,用to[i][j]表示i往后传2^j次会传给谁,查询时像倍增求lca一样查询就行了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
struct node
{
	int a,b,org;
	node(){}
	node(int x,int y,int z){a=x,b=y,org=z;}
}p[maxn<<1];
int n,m,tot;
int to[20][maxn<<1],ans[maxn];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
	return ret*f;
}
bool cmp(const node &a,const node &b)
{
	return a.b<b.b;
}
int main()
{
	n=rd(),m=rd();
	int i,j,a,b;
	for(i=1;i<=n;i++)
	{
		a=rd(),b=rd();
		if(a>b)	p[++tot]=node(a,b+m,i),p[++tot]=node(a+m,b+m+m,i);  //这里把后半句去掉则会WA,不明觉厉
		else	p[++tot]=node(a,b,i),p[++tot]=node(a+m,b+m,i);
	}
	sort(p+1,p+tot+1,cmp);
	for(i=j=1;i<=tot;i++)
	{
		for(;j<tot&&p[j+1].a<=p[i].b;j++);
		to[0][i]=(i==j)?0:j;
	}
	for(j=1;(1<<j)<=tot;j++)	for(i=1;i<=tot;i++)	to[j][i]=to[j-1][to[j-1][i]];
	for(i=1;i<=tot;i++)
	{
		if(p[i].a>m)	continue;
		a=i,b=0;
		for(j=19;j>=0;j--)	if(to[j][a]&&p[to[j][a]].b<p[i].a+m)	a=to[j][a],b+=(1<<j);
		a=to[0][a],b++;
		ans[p[i].org]=b+(p[i].org!=p[a].org);
	}
	for(i=1;i<=n;i++)
	{
		printf("%d",ans[i]);
		if(i<n)	printf(" ");
	}
	return 0;
}

免责声明:文章转载自《【BZOJ4444】[Scoi2015]国旗计划 双指针+倍增》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇IAR常用快捷键和使用小技巧[转]解决Xilinx Platform Studio无法打开 设置 环境变量下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

执行计划--Adhoc和Prepare

在和SQLPass讨论adhoc和Prepare时,有各自不同的观点,我来发表下我的理解,不对之处,敬请指出! Adhoc(即席查询):没有参数化的查询计划会被标记为adhoc,adhoc不能理解为该执行计划不会被重用。 Prepared(预定义):查询中使用到参数的执行计划会被标记为Prepared. 在后续测试中,每次测试之前需要清除执行计划: --清...

Vigenère 密码NOIP 2012 提高组 第一天 第一题

题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码。Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用。 在密码学中,我们称需要加密的信息为明文,用 M 表示;称加密后的信息为密文,用 C 表示;而密钥是一种参数,是将明文转换为密文或...

eslint在webstorm中有错误警告

1. 报错Missing space before function parentheses的问题   解决:在代码目录中,打开.eslint文件,并在rules中添加如下一行代码即可:      "space-before-function-paren": 0 2. 报错eslint: missing semicolon   解决:在rules中添加  ...

触发器(trigger)的作用???

1、触发器,英文名trigger,可以简单的理解为: 就相当于是一个事件的触发装置,当满足了一定的事件触发条件后进行相应的操作 例如当复位set信号到来时,我们就让A<=B,这样一个系统就是一个触发器 下面是一个同步复位端的触发器:   其功能就是当clk触发条件到来时,把b的值传给a。 2、其实现verilog程序是:  module test(c...

Java 读取ANSI文件中文乱码问题解决方式[转]

第一步:首先判断源文件的编码格式: 按照给定的字符集存储文件时,在文件的最开头的三个字节中就有可能存储着编码信息,所以,基本的原理就是只要读出文件前三个字节,判定这些字节的值,就可以得知其编码的格式。其实,如果项目运行的平台就是中文操作系统,如果这些文本文件在项目内产生,即开发人员可以控制文本的编码格式,只要判定两种常见的编码就可以了:GBK和UTF-8。...

SQL Server中行列转换 Pivot UnPivot 【转】

SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P 完整语法: table_source PIVOT( 聚合函数(value_column) FO...