列表

详情


NC51239. Fence Obstacle Course

描述

Farmer John has constructed an obstacle course for the cows' enjoyment. The course consists of a sequence of N fences of varying lengths, each parallel to the x axis. Fence i's y coordinate is i.
The door to FJ's barn is at the origin (marked '*' below). The starting point of the course lies at coordinate (S,N).

   +-S-+-+-+        (fence #N)  +-+-+-+            (fence #N-1)      ...               ...    +-+-+-+          (fence #2)      +-+-+-+        (fence #1) =|=|=|=*=|=|=|      (barn) -3-2-1 0 1 2 3    

FJ's original intention was for the cows to jump over the fences, but cows are much more comfortable keeping all four hooves on the ground. Thus, they will walk along the fence and, when the fence ends, they will turn towards the x axis and continue walking in a straight line until they hit another fence segment or the side of the barn. Then they decide to go left or right until they reach the end of the fence segment, and so on, until they finally reach the side of the barn and then, potentially after a short walk, the ending point. 

Naturally, the cows want to walk as little as possible. Find the minimum distance the cows have to travel back and forth to get from the starting point to the door of the barn.

输入描述

* Line 1: Two space-separated integers: N and S 
* Lines 2..N+1: Each line contains two space-separated integers: , the starting and ending x-coordinates of fence segment i. Line 2 describes fence #1; line 3 describes fence #2; and so on. The starting position will satisfy . Note that the fences will be traversed in reverse order of the input sequence.

输出描述

* Line 1: The minimum distance back and forth in the x direction required to get from the starting point to the ending point by walking around the fences. The distance in the y direction is not counted, since it is always precisely N.

示例1

输入:

4 0 
-2 1
-1 2
-3 0
-2 1

输出:

4

说明:

This problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.
INPUT DETAILS:

Four segments like this:
. +-+-S-+ Fence 4
. +-+-+-+ Fence 3
. +-+-+-+ Fence 2
. +-+-+-+ Fence 1
. |=|=|=*=|=|=| Barn
-3-2-1 0 1 2 3
OUTPUT DETAILS:

Walk positive one unit (to 1,4), then head toward the barn, trivially going around fence 3. Walk positive one more unit (to 2,2), then walk to the side of the barn. Walk two more units toward the origin for a total of 4 units of back-and-forth walking.

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 38ms, 内存消耗: 9080K, 提交时间: 2020-08-07 23:14:50

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#include <bitset>
#include <complex>

#define INF 0x3f3f3f3f
#define IMAX 2147483646;
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define cp complex<double>

using namespace::std;

const int maxn = 211111;
struct T {
	int l, r;
	int val, add;
}t[maxn * 4];

void update(int p) {
	t[p].val = max(t[p * 2].val, t[p * 2 + 1].val);
}

void change(int p) {
	if (t[p].add == 0) return;
	t[p * 2].val = t[p * 2].add = t[p].add;
	t[p * 2 + 1].val = t[p * 2 + 1].add = t[p].add;
	t[p].add = 0;
}

void build(int p, int l, int r) {
	t[p].l = l, t[p].r = r;
	if (l == r) { t[p].val = 0; return; }
	int mid = (l + r) / 2;
	build(p * 2, l, mid);
	build(p * 2 + 1, mid + 1, r);
	update(p);
}

void change(int p, int l, int r, int val) {
	if (t[p].l >= l && t[p].r <= r) {
		t[p].add = val;
		t[p].val = val;
		return;
	}
	change(p);
	int mid = (t[p].l + t[p].r) / 2;
	if (mid >= l) change(p * 2, l, r, val);
	if (mid + 1 <= r) change(p * 2 + 1, l, r, val);
	update(p);
}

int ask(int p, int l, int r) {
	if (t[p].l >= l && t[p].r <= r) return t[p].val;
	change(p);
	int ans = 0;
	int mid = (t[p].l + t[p].r) / 2;
	if (mid >= l)ans = max(ans,ask(p * 2, l, r));
	if (mid < r)ans = max(ans, ask(p * 2 + 1, l, r));
	return ans;
}

int n, s, a[maxn][2], f[maxn][2];
const int l = 200001, p = 100001;

signed main() {
	scanf("%d%d", &n, &s);
	build(1, 1, l);
	f[0][0] = f[0][1] = 0;
	a[0][0] = a[0][1] = 0;
	for (int i = 1,t; i <= n; i++) {
		scanf("%d%d", &a[i][0], &a[i][1]);
		t = ask(1, a[i][0] + p, a[i][0] + p);
		f[i][0] = min(f[t][0] + abs(a[i][0] - a[t][0]),
			f[t][1] + abs(a[i][0] - a[t][1]));

		t = ask(1, a[i][1] + p, a[i][1] + p);
		f[i][1] = min(f[t][0] + abs(a[i][1] - a[t][0]),
			f[t][1] + abs(a[i][1] - a[t][1]));

		change(1, a[i][0] + p, a[i][1] + p, i);
	}
	printf("%d\n", min(f[n][0] + abs(s - a[n][0]),
		f[n][1] + abs(s - a[n][1])));
	
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 32ms, 内存消耗: 5584K, 提交时间: 2020-03-02 18:43:13

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
using namespace std;
const int INF=1e9;
const int maxn=1e5;
int n,s;
int a[maxn*2+5];
int b[maxn*2+5];
int dp[maxn*2+5][2];
int cover[maxn*8+5];
void pushdown(int node)
{
	if(cover[node]!=0)
	{
		cover[node<<1]=cover[node];
		cover[node<<1|1]=cover[node];
		cover[node]=0;
	}
}
void update(int node,int l,int r,int L,int R,int tag)
{
	if(L<=l&&r<=R)
	{
		cover[node]=tag;
		return;
	}
	pushdown(node);
	int mid=(l+r)>>1;
	if(L<=mid) update(node<<1,l,mid,L,R,tag);
	if(R>mid) update(node<<1|1,mid+1,r,L,R,tag);
}
int query(int node,int l,int r,int tag)
{
	if(l==r)
	{
		return cover[node];
	}
	pushdown(node);
	int mid=(l+r)>>1;
	if(tag<=mid) return query(node<<1,l,mid,tag);
	else return query(node<<1|1,mid+1,r,tag);
}
int main()
{
	scanf("%d%d",&n,&s);
	s+=maxn;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i],&b[i]);
		a[i]+=maxn;
		b[i]+=maxn;
	}
	memset(cover,0,sizeof(cover));
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++)
	{
		int x=query(1,1,maxn*2,a[i]);
		int y=query(1,1,maxn*2,b[i]);
		if(x==0) dp[i][0]=abs(a[i]-maxn);
		else dp[i][0]=min(dp[x][0]+abs(a[i]-a[x]),dp[x][1]+abs(a[i]-b[x]));
		if(y==0) dp[i][1]=abs(b[i]-maxn);
		else dp[i][1]=min(dp[y][0]+abs(b[i]-a[y]),dp[y][1]+abs(b[i]-b[y]));
		update(1,1,maxn*2,a[i],b[i],i);
	}
	printf("%d\n",min(dp[n][0]+abs(s-a[n]),dp[n][1]+abs(s-b[n])));
	return 0;
}

上一题