首先是开车旅行
题目地址:
http://fzoj.xndxfz.com/JudgeOnline/problem.php?id=1349
题目大意:
这个我就不说了,看不懂的多读几遍题。(PS:其实我题意读错了3次,捂脸)
题解:
因为A和B是一人开一天,所以我们就可以将A与B各开一天看作一次开车。这样的话只要确定了起始位置,我们就可以通过倍增的方法快速找到总距离不超过X的所能到达的最远的点了。另外多说一句,这里如果是直接用n的时间查找最远点应该会超时,而如果用倍增可以将这里的n变为logn。
个人认为这道题比较坑的是预处理。也就是找距离当前城市第一近和第二近的城市。这个最开始我是想直接把全部点快排一遍,然后再找最近和第二近的城市,然后。。。我发现这个很难写,放弃了。这个时候,万能的Apache553给我介绍了一下set。我又看了一下Y_sofun的代码才A掉这道题。
下面就贴代码吧。
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
struct node
{
int ord,high;
friend bool operator<(node x,node y)
{
return x.high<y.high;
}
}h[N];
struct node2
{
int ord,val,high;
friend bool operator<(node2 x,node2 y)
{
if(x.val==y.val)
{
return x.high<y.high;
}
return x.val<y.val;
}
node2 () {}
node2(int a,int b,int c) : val(a),ord(b),high(c) {}
}t[10];
int n,fa[3][N],d[3][N],xaq,xbq,m,x0;
int grand[N][20],disa[N][20],disb[N][20];
set<node> S;
set<node>::iterator iter;
inline int read()
{
int out=0,flagg=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') flagg=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
out=out*10+ch-'0';
ch=getchar();
}
return out*flagg;
}
void Init()
{
memset(grand,0,sizeof(grand));
memset(h,0,sizeof(0));
memset(fa,0,sizeof(fa));
// scanf("%d",&n);
n=read();
int cnt=0,i,j;
for(i=1;i<=n;i++)
{
// scanf("%d",&h[i].high);
h[i].high=read();
h[i].ord=i;
}
for(i=n;i>=1;i--)
{
cnt=0;
S.insert(h[i]);
iter=S.find(h[i]);
if(iter!=S.begin())
{
--iter;
t[++cnt]=node2(abs((*iter).high-h[i].high),(*iter).ord,(*iter).high);
if(iter!=S.begin())
{
--iter;
t[++cnt]=node2(abs((*iter).high-h[i].high),(*iter).ord,(*iter