Description

  

   题目链接

  

  

  

Solution

磕了3个半小时没做出来的题,就是全场崩.

  

   首先对于一个人的答案是很好求的,显然是选择左端点在此人区间中,右端点最远(最靠右)的人作为下一个接棒人.因此用线段树维护一下就可以了,注意判断跨环边界的情况(n->1).

  

   时间复杂度$ \mathcal O(n^2 \log n) $.

  

   接着我再想,如果按左端点从大到小从右往左注意处理,每个人其实就是选择那些左端点处于自己区间中的人作为后继,选择它们的答案最小值即可.然而终止点也是不断移动的,所以每个人的答案在之后的人看是动态的.考虑很难修改,就猜性质,猜了个性质,用2h实现程序暴力和数据生成器,然后一组数据见祖宗.

  

   TMD

  

   稍微换一下思路,与其想办法维护接力方案,不如直接考虑计算每个人,并优化这个过程.

  

   可以发现,每个人选择哪一个人作为下一棒是唯一确定的(左端点在区间内的人中,右端点最远的那个人). 且每传一次棒,贡献的距离也是唯一确定的(当前人的右端点与下一棒的右端点的距离).

  

   确定下一棒可以用线段树直接模拟.

  

   对于每个人\(i\),我们相当于要知道从他开始至少传多少棒之后,总距离贡献超过了\(m-len_i\). 其中\(len_i\)表示这个人的区间长度减一.

  

   那么倍增出传\(2^k\)步后是谁,以及总距离贡献是多少.

  

   对于每个人直接从大到小枚举\(k\)逐步逼近目标步数即可.

  

   总时间复杂度是\(\mathcal O (n \log n)\)

  

  

  

Code

  

#include <cstdio>
#include <algorithm>
#define mp make_pair
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=200005;
const int INF=1e9;
int n,m;
int diz[N*2],dcnt,who[N*2];
int go[N][19];
ll d[N][19];
struct Man{
int l,r,id;
int get(){
if(l<r) return r-l;
return r+(dcnt-l);
}
}p[N];
void readData(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].l,&p[i].r);
p[i].id=i;
}
}
void Diz(){
for(int i=1;i<=n;i++){
diz[++dcnt]=p[i].l;
diz[++dcnt]=p[i].r;
}
sort(diz+1,diz+1+dcnt);
dcnt=unique(diz+1,diz+1+dcnt)-diz-1;
for(int i=1;i<=n;i++){
p[i].l=lower_bound(diz+1,diz+1+dcnt,p[i].l)-diz;
p[i].r=lower_bound(diz+1,diz+1+dcnt,p[i].r)-diz;
}
}
bool cmpMan(const Man &a,const Man &b){
return a.l<b.l;
}
pii max(pii x,pii y){
return x.first>y.first?x:y;
}
namespace SEG{/*{{{*/
const int S=N*4;
int rt,sz;
int ch[S][2];
pii info[S];
inline void pushup(int u){
info[u]=max(info[ch[u][0]],info[ch[u][1]]);
}
void build(int &u,int l,int r){
u=++sz;
if(l==r){
info[u]=mp(-INF,-INF);
return;
}
int mid=(l+r)>>1;
build(ch[u][0],l,mid);
build(ch[u][1],mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int pos,pii val){
if(l==r){
info[u]=val;
return;
}
int mid=(l+r)>>1;
if(pos<=mid)
modify(ch[u][0],l,mid,pos,val);
else
modify(ch[u][1],mid+1,r,pos,val);
pushup(u);
}
pii query(int u,int l,int r,int L,int R){
if(L<=l&&r<=R) return info[u];
int mid=(l+r)>>1;
if(R<=mid) return query(ch[u][0],l,mid,L,R);
else if(mid<L) return query(ch[u][1],mid+1,r,L,R);
else
return max(query(ch[u][0],l,mid,L,mid),query(ch[u][1],mid+1,r,mid+1,R));
}
}/*}}}*/
void calc(){
SEG::build(SEG::rt,1,dcnt);
for(int i=1;i<=n;i++)
SEG::modify(SEG::rt,1,dcnt,p[i].l,mp(p[i].l>p[i].r?p[i].r+dcnt:p[i].r,i));
for(int i=1;i<=n;i++){
int x;
pii get;
if(p[i].l<p[i].r)
get=SEG::query(SEG::rt,1,dcnt,p[i].l+1,p[i].r);
else{
get=mp(-INF,-INF);
if(p[i].l<dcnt)
get=SEG::query(SEG::rt,1,dcnt,p[i].l+1,dcnt);
pii tmp=SEG::query(SEG::rt,1,dcnt,1,p[i].r);
tmp.first+=dcnt;
get=max(get,tmp);
}
go[i][0]=get.second;
d[i][0]=get.first-(p[i].l>p[i].r?p[i].r+dcnt:p[i].r);
}
for(int j=1;j<=18;j++)
for(int u=1;u<=n;u++){
go[u][j]=go[go[u][j-1]][j-1];
d[u][j]=d[u][j-1]+d[go[u][j-1]][j-1];
}
}
void solve(){
for(int i=1;i<=n;i++){
int ans=1;
int u=i,last=dcnt-p[i].get();
for(int j=18;j>=0;j--)
if(d[u][j]<last){
last-=d[u][j];
ans+=(1<<j);
u=go[u][j];
}
printf("%d ",ans+1);
}
puts("");
}
int main(){
readData();
Diz();
calc();
solve();
return 0;
}

【BZOJ4444】国旗计划的更多相关文章

  1. [bzoj4444] 国旗计划 双指针+倍增

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

  2. bzoj4444 国旗计划

    题目链接 倍增,预处理出每个点往后$2^i$个应该选哪个人 我用的treap就是快 #include<algorithm> #include<iostream> #includ ...

  3. luogu4155/bzoj4444 国旗计划 (倍增)

    成环,把每个区间变成两个然后展开成链 一个人的下一个人肯定是在彼此相交的基础上,右端点越大越好 于是就把它连到相交的.右端点最大的点上,连成一棵树 于是每次只要从某个节点开始,一直在树上跳到覆盖了一个 ...

  4. 【bzoj4444 scoi2015】国旗计划

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

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

    [BZOJ4444][Scoi2015]国旗计划 Description A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形 ...

  6. [BZOJ4444] [Luogu 4155] [LOJ 2007] [SCOI2015]国旗计划(倍增)

    [BZOJ4444] [Luogu 4155] [LOJ 2007] [SCOI2015]国旗计划(倍增) 题面 题面较长,略 分析 首先套路的断环为链.对于从l到r的环上区间,若l<=r,我们 ...

  7. 【bzoj4444】[Scoi2015]国旗计划 倍增

    题目描述 给出一个圈和若干段,问:对于所有的 $i$ ,选择第 $i$ 段的情况下,最少需要选择多少段(包括第 $i$ 段)能够覆盖整个圈? 输入 第1行,包含2个正整数N,M,分别表示边防战士数量和 ...

  8. 【BZOJ4444】国旗计划 - 决策单调性

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

  9. [bzoj4444] [loj#2007] [洛谷P4155] [Scoi2015] 国旗计划

    Description \(A\) 国正在开展一项伟大的计划--国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 ...

  10. bzoj 4444: [Scoi2015]国旗计划

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

随机推荐

  1. 手机app测试讲座

    活动简介: 移动 面向人群: 测试工程师,软件工程师,系统运维工程师,项目经理 活动时间 基于C#的移动应用程序测试(1) 2016年5月18日 上午9:00 基于C#的移动应用程序测试(2) 201 ...

  2. 20155331《网络对抗》Exp7 网络欺诈防范

    20155331<网络对抗>Exp7 网络欺诈防范 实验内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有: 简单应用SET工具建立冒名网站 et ...

  3. 总是套路留人心, JAVA提供的套路: LinkedHashMap实现LRU缓存; InvocationHandler实现动态代理; fork/join实现窃取算法

    1. LinkedHashMap实现LRU缓存 LRU缓存核心是根据访问顺序排序, 自动移除队尾缓存, LinkedHashMap已经实现了这些要求: public LRUCache<K, V& ...

  4. 蓝牙disable流程简述

    蓝牙关闭的流程比打开流程要简单,主要就是一些profile的断连以及协议栈相关结构的释放. 这里简单说一下其流程,就直接从协议栈的disable的接口说起了. static int disable(v ...

  5. CS190.1x-ML_lab5_pca_student

    这次lab也是最后一次lab了,前面两次lab介绍了回归和分类,特别详细地介绍了线性回归和逻辑回归,这次的作业主要是非监督学习--降维,主要是PCA.数据集是神经科学的数据,来自于Ahrens Lab ...

  6. c语言连接mysql数据库的实现方法

    C语言连接mysql数据库,需要相应的头文件和lib文件,如果你安装Mysql数据库,会在安装目录下找到这些库文件,如果没有安装,也可以在网上找到 我这里也有一份网上找到的:/201205/other ...

  7. 机器视觉及图像处理系列之二(C++,VS2015)——图像级的人脸识别(1)

    接上一篇,一切顺利的话,你从github上clone下来的整个工程应该已经成功编译并生成dll和exe文件了:同时,ImageMagic程序亦能够打开并编辑图像了,如此,证明接下来的操练你不会有任何障 ...

  8. 自己动手写Impala UDF

    本文由  网易云发布. 概述 出于对可扩展性和性能的考虑,UDF已变成大数据生态圈查询引擎的必备功能之一,无论是Calcite.Hive.Impala都对其进行支持,但是UDF的支持有利也有弊,好处在 ...

  9. 微软职位内部推荐-Senior Program Manager

    微软近期Open的职位: Title: Senior Program Manager – Bing Multimedia Relevance Group: Search Technology Cent ...

  10. 这个不是第一次作业----艰难的安装Android studio历程

    之前只听说过eclipse,后来从室友处得知,还有一个安卓的开发工具叫做Android studio,上网百度后发现网友普遍说Android studio比eclipse快,没想太多,删E装A. 在装 ...