[SCOI2015]国旗计划

[SCOI2015]国旗计划

https://ac.nowcoder.com/acm/problem/20302

非常考验技巧的一题...emm这个我最不会了...

首先断环为链,也就是把士兵和站台复制一份放在后面,这样只需要考虑覆盖一个区间而已

因为区间两两不包含,所以当选择了第个士兵后

现在覆盖了

那么从左端点不大于里选,一定是选右端点最大的最优秀了

那么这样选择的士兵就固定了...

关键就找下一个士兵的过程,可以二分预处理

但是倍增更快!!!

说起来 简单,但还是不会写,实现能力太差了...

#include <bits/stdc++.h>
using namespace std;
int n,m;
const int maxn = 4e5+10;
struct soldier
{
    int id,l,r;
}a[maxn];
bool com(soldier a,soldier b){ return a.l<b.l; }
int flow[maxn],f[maxn][22];
void solve(int k)
{
    int limit = a[k].l+m, ans = 1, index = k;
    for(int i=20;i>=0;i-- )
        if( f[k][i]!=0&&a[f[k][i]].r<limit )
            ans += (1<<i),k=f[k][i];
    flow[a[index].id] = ans+1;        
}
void init()
{
    for(int i=1,index = i;i<=2*n;i++)
    {
        while( index<=2*n && a[index].l<=a[i].r )    index++;//其实这里可以二分更快 
        f[i][0] = index-1;//最靠近r的战士,说明他的r也最远 
    }
    for(int i=1;i<=20;i++)
    for(int j=1;j<=2*n;j++)    
        f[j][i] = f[f[j][i-1]][i-1];
}
int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].l,&a[i].r);
        if( a[i].r<a[i].l )    a[i].r+=m;
        a[i].id = i;    
    }    
    sort( a+1,a+1+n,com );//注意先排序再复制 
    for(int i=n+1;i<=2*n;i++)
        a[i]=a[i-n],a[i].l+=m,a[i].r+=m;
    init();
    for(int i=1;i<=n;i++)    solve(i);
    for(int i=1;i<=n;i++)    printf("%d ",flow[i] );
}
全部评论

相关推荐

10-28 11:04
已编辑
美团_后端实习生(实习员工)
一个2人:我说几个点吧,你的实习经历写的让人觉得毫无含金量,你没有挖掘你需求里的 亮点, 让人觉得你不仅打杂还摆烂。然后你的简历太长了🤣你这个实习经历看完,估计没几个人愿意接着看下去, sdk, 索引这种东西单拎出来说太顶真了兄弟,好好优化下简历吧
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
11-29 11:21
门头沟学院 Java
点赞 评论 收藏
分享
评论
2
收藏
分享
牛客网
牛客企业服务