题意:
有一个大厦,里面有一个电梯和nnn个需求使用电梯的人,每个人有一个出发楼层aia_{i}ai和到达楼层bib_{i}bi,这个大厦高mmm楼,最低是111楼,电梯一次最多可以搭载kkk个人。电梯有一个特性,上行的时候可以在任意地方更改方向向下行,而下行的时候只能在到达111楼后再改变方向向上行,当然无论何时都可以停下来上下人,问电梯至少需要几分钟才可以把nnn个人送达目的楼层并且回到一楼?
方法:
一个人是从aia_{i}ai到bib_{i}bi的,那么我们可以在数轴上aia_{i}ai到bib_{i}bi的地方覆盖上一条线段,某个地方xxx覆盖了ttt条线段,就说明一共有ttt个人途径这里,那么电梯就一定要到xxx这个地方ceil(t,k)ceil(t,k)ceil(t,k)次,那么我们只需要找到最大的这个ceil(t,k)ceil(t,k)ceil(t,k)。首先我们就得实现线段覆盖,容易想到的方法是线段树区间修改,但难以面对大范围的数据,因此有一种差分线段覆盖的方法,如果要覆盖线段在[x,y][x,y][x,y],那么只需要在xxx这个地方+1,yyy这个地方-1即可。即设定一对pairpairpair,firstfirstfirst是位置,secondsecondsecond是差分量,那么覆盖[x,y][x,y][x,y]就仅需要加入两个pairpairpair:<x,1>,<y,−1><x,1>,<y,-1><x,1>,<y,−1>。按照端点位置排序后,当我们读入一个就添加到sumsumsum变量内,读入一个之后的sumsumsum即使现在这个pairpairpair和下个pairpairpair之间的线段覆盖数。
完成线段覆盖之后,我们就开始找距离和,如果只需要走一次的线段最高覆盖到h1h_{1}h1,走两次的线段最高覆盖到h2h_{2}h2,如果h1<h2h_{1}<h_{2}h1<h2,那么我们最高两次都需要到达最高处,如果h1>h2h_{1}>h_{2}h1>h2,那么我们的路线是1->h2h_{2}h2->1,1->h1h_{1}h1->1,因此,我们把所有极值点插入setsetset,然后从后往前遍历,每次遇到比之前遇到的次数多的极值点,我们就停下来计算这一个极值点与遇到的最大点的次数差需要走多远,加入答案。
#include<bits/stdc++.h>
#define ll long long
#define fr first
#define se second
#define int long long
using namespace std;
int read()
{
int ret=0,base=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') base=-1;
ch=getchar();
}
while(isdigit(ch))
{
ret=(ret<<3)+(ret<<1)+ch-48;
ch=getchar();
}
return ret*base;
}
inline int ceil_(int a,int b)
{
return a%b?a/b+1:a/b;
}
vector<pair<int,int>>up,down;
set<pair<int,int>>set1;
int n,k,m;
signed main()
{
n=read();k=read();m=read();
for(int i=1;i<=n;i++)
{
int u=read(),v=read();
if(u<v)
{
up.push_back(make_pair(u,1));
up.push_back(make_pair(v,-1));
}
else
{
down.push_back(make_pair(v,1));
down.push_back(make_pair(u,-1));
}
}
sort(up.begin(),up.end());
sort(down.begin(),down.end());
int sum=0;
for(int i=0;i<up.size();i++)
{
if(up[i].se==-1) set1.insert({up[i].fr,sum});
sum+=up[i].se;
}
sum=0;
for(int i=0;i<down.size();i++)
{
if(down[i].se==-1) set1.insert({down[i].fr,sum});
sum+=down[i].se;
}
auto it=set1.end();it--;
int max1=0,ans=0;
while(1)
{
int pos=it->fr,t=it->se;
if(ceil_(t,k)>max1)
{
int x=ceil_(t,k)-max1;
ans+=2*x*(pos-1);
max1+=x;
}
if(it--==set1.begin()) break;
}
cout<<ans;
return 0;
}
901

被折叠的 条评论
为什么被折叠?



