[SCOI2015]国旗计划

题目描述

A 国正在开展一项伟大的计划 —— 国旗计划。这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈。这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 N 名优秀的边防战上作为这项计划的候选人。

A 国幅员辽阔,边境线上设有 M 个边防站,顺时针编号 1 至 M 。

每名边防战士常驻两个边防站,并且善于在这两个边防站之间长途奔袭,我们称这两个边防站之间的路程是这个边防战士的奔袭区间。

N名边防战士都是精心挑选的,身体素质极佳,所以每名边防战士的奔袭区间都不会被其他边防战士的奔袭区间所包含。

现在,国十安全局局长希望知道,至少需要多少名边防战士,才能使得他们的奔袭区间覆盖全部的边境线,

从而顺利地完成国旗计划。不仅如此,安全局局长还希望知道更详细的信息:对于每一名边防战士,在他必须参加国旗计划的前提下,

至少需要多少名边防战士才能覆盖全部边境线,从而顺利地完成国旗计划。

输入输出格式

输入格式:

第一行,包含两个正整数 N,M,分别表示边防战士数量和边防站数量。

随后 N行,每行包含两个正整数。其中第 ii 行包含的两个正整数 Ci、Di 分别表示 i号边防战士常驻的两个边防站编号,

Ci? 号边防站沿顺时针方向至 Di? 号边防站力他的奔袭区间。数据保证整个边境线都是可被覆盖的。

输出格式:

输出数据仅 1 行,需要包含 N个正整数。其中,第 j 个正整数表示 j 号边防战士必须参加的前提下至少需要多

少名边防战士才能顺利地完成国旗计划。

输入输出样例

输入样例#1:

4 8
2 5
4 7
6 1
7 3

输出样例#1:

3 3 4 3

说明

N?2×10^5,M<10^9,1?Ci?,Di??M 。

解:

首先破链成环,就转化为了区间覆盖问题。

每一个区间都不能被其他区间所包含,

也就是如果li<lj,那么一定满足ri<rj,然后就可以贪心。

假设要覆盖整个区间,那么选择的线段是确定的,即每一个战士要找的下一个战士都是确定的。

这样可以按照左端点排序,预处理出每个战士的下一个接力者。

对于必须有这个战士参与,我们可以以这个战士为起点,寻找经过一圈之后再次回来最少需要多少条线段。

因为是链,所以我们用倍增预处理。

f[i][j]表示从i点走2j步到达的点,如果f[i][j]所到达的点没有超出m,就可以从i点走2j步,到达下一个点。

另外,使用set(stl大法好)可以减少代码量。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<cmath>
 8 #include<set>
 9 #define ll long long
10 #define DB double
11 #define mod 1000000007
12 #define eps 1e-3
13 #define inf 147483600
14 using namespace std;
15 inline int read()
16 {
17     int x=0,w=1;char ch=getchar();
18     while(!isdigit(ch)){if(ch==‘-‘) w=-1;ch=getchar();}
19     while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();
20     return x*w;
21 }
22 const int N=2e6+10;
23 int n,m,cnt,top;
24 int f[N][30],ans[N];
25 struct yuh{
26   int l,r,id;
27 }c[N];
28 bool cmp(yuh x,yuh y){ return x.l<y.l;}
29 set< pair <int,int> >s;
30 void work(int x)
31 {
32     int id=c[x].id,L=c[x].l+m;
33     for(int i=20;i>=0;--i)
34      if(f[x][i])
35       if(c[f[x][i]].r<L)
36        x=f[x][i],ans[id]+=(1<<i);
37 }
38 int main()
39 {
40     // freopen("flag.in","r",stdin);
41     // freopen("flag.out","w",stdout);
42     n=read();m=read();
43     for(int i=1;i<=n;++i)
44     {
45         int l,r;l=read();r=read();
46         if(l>r) r+=m;
47         cnt++;c[cnt]=(yuh){l,r,i};
48         cnt++;c[cnt]=(yuh){l+m,r+m,0};
49     }
50     sort(c+1,c+cnt+1,cmp);
51     s.insert(make_pair(c[cnt].l,cnt));
52     for(int i=cnt-1;i>=1;--i)
53     {
54         f[i][0]=(--s.upper_bound((make_pair(c[i].r,inf))))->second;
55         s.insert(make_pair(c[i].l,i));
56     }
57     for(int i=1;i<=20;++i)
58      for(int j=cnt;j>=1;--j)
59       f[j][i]=f[f[j][i-1]][i-1];
60     for(int i=1;i<=cnt;++i)
61      if(c[i].id) work(i);
62     for(int i=1;i<=n;++i)
63      printf("%d ",ans[i]+2);
64     return 0;
65 }

原文地址:https://www.cnblogs.com/adelalove/p/8492346.html

时间: 2024-08-04 03:33:16

[SCOI2015]国旗计划的相关文章

4444: [Scoi2015]国旗计划

4444: [Scoi2015]国旗计划 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 485  Solved: 232 Description A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这 项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的边防战上作为这 项计划的候选人. A国幅员辽阔,边境线上设有M个边防站,顺时针编号1至M.每名边防战士常驻两个边防站,并且善于

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

[BZOJ4444][Scoi2015]国旗计划 Description A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名优秀的边防战上作为这项计划的候选人. A国幅员辽阔,边境线上设有M个边防站,顺时针编号1至M.每名边防战士常驻两个边防站,并且善于在这两个边防站之间长途奔袭,我们称这两个边防站之间的路程是这个边防战士的奔袭区间.n名边防战士都是精心挑选的,身体素质极佳,所以

4444: [Scoi2015]国旗计划|贪心|倍增

由于没有区间被其它区间包括这个条件,也就是假设li<lj那么一定满足ri<rj,就能够贪心搞一搞了. 假如区间[l,r]都已经被覆盖,那么能够继续找一个li在[l,r]范围内的最大的一个,继续扩展覆盖的区间,然后再以相同的方式找下一个战士 这样能够依照左端点排序,然后每个战士要找的下一个战士都是确定的,然后用倍增找出一共须要多少战士就能够了 #include<algorithm> #include<iostream> #include<cstdlib> #i

BZOJ4444 : [Scoi2015]国旗计划

首先将坐标离散化,因为区间互不包含,可以理解为对于每个起点输出最少需要多少个战士. 将环倍长,破环成链,设$f[i]$表示区间左端点不超过$i$时右端点的最大值,可以通过$O(n)$递推求出. 那么如果将$f[i]$看成$i$的祖先的话,它实际上形成了一棵以$2n$为根的树. 首先暴力计算出1号点的答案$t$,设$L=t-1$. 然后dfs这棵树,用一个栈按深度依次保存每个点到根路径上的点. 对于一个点,只需要从$L$开始暴力枚举答案,然后$O(1)$检验即可. 因为每个点的答案相差不超过1,所

LibreOJ #2007. 「SCOI2015」国旗计划

二次联通门 : LibreOJ #2007. 「SCOI2015」国旗计划 --by Claris /* LibreOJ #2007. 「SCOI2015」国旗计划 跪膜Claris... */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void read (int &

AC日记——「SCOI2015」国旗计划 LiBreOJ 2007

#2007. 「SCOI2015」国旗计划 思路: 跪烂Claris 代码: #include <cstdio> #include <algorithm> #define maxn 800010 int n,m,ai[maxn][2],bi[maxn],f[maxn<<1],st[maxn]; int g[maxn],nxt[maxn<<1],q[maxn<<1],t,ans[maxn],L,x,y,i; inline void in(int&a

国旗计划

题目:A 国正在开展一项伟大的计划 -- 国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 N N 名优秀的边防战上作为这项计划的候选人. A 国幅员辽阔,边境线上设有 M M 个边防站,顺时针编号 1 1 至 M M.每名边防战士常驻两个边防站,并且善于在这两个边防站之间长途奔袭,我们称这两个边防站之间的路程是这个边防战士的奔袭区间. N N 名边防战士都是精心挑选的,身体素质极佳,所以每名边防战士的奔袭区间

贪心(qwq)习题题解

贪心(qwq)习题题解 SCOI 题解 [ SCOI2016 美味 ] 假设已经确定了前i位,那么答案ans一定属于一个区间. 从高位往低位贪心,每次区间查找是否存在使此位答案为1的值. 比如6位数确定了前三位\((101...)_2\),下一位应该是1 那么\(a_i+x_i\)的查找区间为:\([(101100)_2,(101111)_2]\) ,同理如果应该是0则为\([(101000)_2,(101011)_2]\). 注意到有区间\([l,r]\)范围的限制所以用主席树维护即可. [

省选之前的未完成的计划(截至到省选)

PLAN OF THE COMING HEOI good problems:-bzoj4823:[Cqoi2017]老C的方块 [*]-bzoj3171:[Tjoi2013]循环格 [*]-bzoj4200:[Noi2015]小园丁与老司机 [*]-bzoj1061:[Noi2008]志愿者招募 [*]-bzoj3600:没有人的算术 [*]-bzoj2806:[Ctsc2012]Cheat [*]-bzoj2219:数论之神 [*]-bzoj2595:[Wc2008]游览计划 [*]-bzoj