scoi2015 bzoj4444 国旗计划
来源:互联网 发布:马踏棋盘贪心算法 编辑:程序博客网 时间:2024/05/18 00:10
http://www.lydsy.com/JudgeOnline/problem.php?id=4444
其实我并没想到正解~~
首先把环拆成链,两倍链。
然后要离散化
f[i]表示左端点在i之前的最多能覆盖到哪个位置
可以先处理f[i]在i的时候最多能覆盖到哪里,然后向前缀和一样搞一下。
暴力计算出1-m的最小次数L,所有人的最小人数和这个数之差的绝对值不会超过1. ----------------------这是一个性质,因为假设把1覆盖的区间拿走,一定会用1-2条覆盖缺口。再加入必须的一条,可能使0-2条变得无用。 但是综合一下,波动不会超过2,毕竟求1的时候是最优的,覆盖会尽可能大。
我们考虑一个点i,如果能求出最少用几次到i+m之后,答案就出来了。而这就是可以用f[]这样搞出来的.
最直接的做法就是暴力枚举每个点i,一直跳f[i],看最少用几次到i+m之后,但这个时间复杂度明显很高。
由于有性质,我们可以对于每个点的跳跃次数从L-1开始跳(前提是我们知道当前点跳L-1会到哪里,如果知道,就算是暴力也可以优化很多(波动不超过2,接近On了))
现在问题就转化成:求每个点跳L-1次会到达哪个点u,然后从u暴力枚举一直跳到i+1之后。
我们发现从i到f[i]有点类似于一个链接(链表),假设每个i到f[i]建了一条边,构成森林。 我们会发现,不管从哪个点出发,最后都会到达2m.
也就是说,如果我们把整棵树倒过来,他就是一棵以2m为根的树。
然后我们dfs遍历整棵树,同时用栈维护从根到当前点u这条路径上的点(也就是它一直跳到2m的路径,然后对于每个点,就可以很快找到跳L-1次会到哪个点了,因为他要求的答案就在栈中。)
然后,就很好做了。
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>using namespace std;const int maxn=400000+20;int n,m;int read(){int res=0;char c=getchar();for(;c<'0'||c>'9';c=getchar());for(;c>='0'&&c<='9';c=getchar())res=res*10+c-'0';return res;}struct edge{int v,next;}e[maxn<<1];int head[maxn<<1];int k;void add(int u,int v){if(u==v)return ;e[k].v=v;e[k].next=head[u];head[u]=k++;}int det[maxn<<1];int a[maxn][2];int cnt,len,L;int st[maxn];int f[maxn<<1];//从i最多能到j int sta[maxn<<1];int ans[maxn];int top;int find(int x){return lower_bound(det+1,det+len+1,x)-det;}void dfs(int u){sta[++top]=u;if(u<=m)for(int i=L;;i++)if(sta[top-i]>=u+m){ans[u]=i;break;}for(int i=head[u];~i;i=e[i].next)dfs(e[i].v);top--;}int main(){memset(head,-1,sizeof(head));k=0;cnt=0;n=read(),m=read();for(int i=1;i<=n;i++){a[i][0]=read();a[i][1]=read();det[++cnt]=a[i][0];det[++cnt]=a[i][1];}sort(det+1,det+cnt+1);len=unique(det+1,det+cnt+1)-det-1;m=len;for(int i=1;i<=n;i++){int x=find(a[i][0]),y=find(a[i][1]);st[i]=x;if(x<=y){f[x]=max(f[x],y);f[x+m]=max(f[x+m],y+m);}else {f[1]=max(f[1],y);f[x]=max(f[x],y+m);f[x+m]=max(f[x+m],2*m);}}for(int i=1;i<=2*m;i++)f[i]=max(f[i],f[i-1]);//维护前缀 L=-1;top=0;for(int i=1;i<=m;i=f[i])L++;for(int i=1;i<=2*m;i++)add(f[i],i);dfs(2*m);for(int i=1;i<=n;i++)printf("%d ",ans[st[i]]);return 0;}
- scoi2015 bzoj4444 国旗计划
- BZOJ4444: [Scoi2015]国旗计划 解题报告
- BZOJ4444 SCOI2015国旗计划 根据性质优化贪心
- 4444: [Scoi2015]国旗计划
- 4444: [Scoi2015]国旗计划
- 4444: [Scoi2015]国旗计划
- bzoj 4444: [Scoi2015]国旗计划
- BZOJ 4444 [Scoi2015]国旗计划
- 4444: [Scoi2015]国旗计划|贪心|倍增
- BOZJ 4444([Scoi2015]国旗计划-区间问题)
- bzoj 4444: [Scoi2015]国旗计划 递推
- [SCOI2015][吐槽]******SCOI2015
- SCOI2015小记
- scoi2015祭
- SCOI2015小记
- SCOI2015 day1
- SCOI2015 day1
- 路国旗
- 下载离线aptana的eclipse插件
- Redis和Memcache的区别分析
- 代码走查
- Maven学习笔记一Maven的介绍与优点
- CocoaPods 错误 target overrides the `OTHER_LDFLAGS`...
- scoi2015 bzoj4444 国旗计划
- [Mark] 百度地图 Https
- <<爬坑一>>有关上传头像中的截取图片
- LeetCode 218. The Skyline Problem
- 【poj 2528】Mayor's posters 题意&题解&代码(C++)
- NYOJ22-吝啬的国度
- hadoop_1_完全分布式
- 单例类型初体验与在链式调用中的应用
- 你真的会写单例模式吗——Java实现