• codevs 1199 开车旅行


    题意:

    有n个城市每个城市都有一个海拔,城市与城市之间的距离为海拔的差的绝对值,现在有两个人A,B开车去旅行,首先A开车,然后B开车,依次交换,然后A会开向离他第二近的城市,B会开向离他最近的那个城市(规定距离相同时,海拔越低的城市距离越短),并且只能从左向右走,第一个问题问,他们总共行驶X个单位,问从哪个城市出发A开的距离比上B开的距离比值最小?第二个问题问,从城市S出发行驶X个单位后,A和B各自开了多少?

    题解:

    ①从一个城市到达其他的城市只会是通过AB一轮的转移,这个转移是单调的,很显然倍增。

    ②现在的问题是解决倍增的初始值,就是处理出离城市i最近的城市和第二近的城市是谁,在下弱爆了,只能用set了QAQ

    代码:

    #include <iostream>
    #include <cstdio>
    #include <set>
    #include <map>
    #include <algorithm>
    using namespace std;
    #define ll long long
    const int N = 1e5 + 7;
    const ll inf = 5e9 + 7;
    map <ll, int> id;
    set <ll> S;
    ll va[20][N], vb[20][N], h[N];;
    ll cnta, cntb, x;
    struct node {ll h, c;} p[5];
    int n, s, q;
    int anc[20][N], Anxt[N], Bnxt[N];
    bool cmp (node a, node b) {
    	if (a.c == b.c) return a.h < b.h;
    	return a.c < b.c;
    }
    void query (int s, ll x, ll &cnta, ll &cntb) {
    	for (int i = 18; i >= 0; --i) {
    		if (anc[i][s] && va[i][s] + vb[i][s] <= x) {
    			cnta += va[i][s];
    			cntb += vb[i][s];
    			x -= va[i][s] + vb[i][s];
    			s = anc[i][s];
    		}
    	}
    	if (Anxt[s] && abs(h[Anxt[s]] - h[s]) <= x) cnta += abs(h[Anxt[s]] - h[s]);
    }
    
    void prepare () {
    	S.insert(-inf), S.insert (inf);
    	for (int i = n; i >= 1; --i) {
    		S.insert(h[i]);
    		p[2].h = *--S.find(h[i]);
    		p[3].h = *++S.find(h[i]);
    		if (p[2].h != -inf) p[1].h = *--S.find(p[2].h);
    		else p[1].h = -inf;
    		if (p[3].h !=  inf) p[4].h = *++S.find(p[3].h);
    		else p[4].h =  inf;
    		for (int k = 1; k <= 4; ++k) p[k].c = abs(p[k].h - h[i]);
    		sort (p + 1, p + 5, cmp);
    		Bnxt[i] = id[p[1].h];
    		Anxt[i] = id[p[2].h];
    	}
    	for (int i = 1; i <= n; ++i) {
    		int A = Anxt[i], B = Bnxt[A];
    		if (A) va[0][i] = abs(h[A] - h[i]);
    		if (B) vb[0][i] = abs(h[B] - h[A]);
    		anc[0][i] = B;
    	}
    	for (int i = 1; i <= 18; ++i) {
    		for (int j = 1; j <= n; ++j) {
    			anc[i][j] = anc[i-1][anc[i-1][j]];
    			va[i][j] = va[i-1][j] + va[i-1][anc[i-1][j]];
    			vb[i][j] = vb[i-1][j] + vb[i-1][anc[i-1][j]];
    		}
    	}
    }
    
    int main () {
    	scanf ("%d", &n);
    	for (int i = 1; i <= n; ++i) {
    		cin >> h[i];
    		id[h[i]] = i;
    	}
    	prepare();
    	cin >> x;
    	double mini = 1e9 + 7; int id = 0;
    	for (int i = 1; i <= n; ++i) {
    		cnta = 0, cntb = 0;
    		query (i, x, cnta, cntb);
    		if (1.0 * cnta / cntb < mini) {
    			mini = 1.0 * cnta / cntb;
    			id = i;
    		}
    	}
    	cout << id << endl;
    	scanf ("%d", &q);
    	while (q--) {
    		cin >> s >> x;
    		cnta = 0, cntb = 0;
    		query (s, x, cnta, cntb);
    		cout << cnta << " " << cntb << endl;
    	}
    	return 0;
    }
    

      

    总结:

    还是那句话,一开始尽量不要想细节,先想想总体的思路,要维护什么,要用什么算法就好了,不然总是把自己搞晕,这道题就是一个大水题,就是为了倍增去用set找边界。。。

  • 相关阅读:
    上周热点回顾(6.5-6.11)团队
    云计算之路-阿里云上:14:20-14:55博客后台2台服务器都CPU 100%引发的故障团队
    牛客网Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤
    牛客网Java刷题知识点之equals和hashcode()
    spark运行时出现Neither spark.yarn.jars nor spark.yarn.archive is set错误的解决办法(图文详解)
    大数据的结构类型(结构化数据、半结构化数据、准结构化数据、非结构化数据)
    Spark 1.6.2 + Beam 2.0.0读取Mongodb数据进行相应逻辑处理
    Docker的基本概念
    Docker的基本构架
    Docker概念学习系列之Docker是什么?(1)
  • 原文地址:https://www.cnblogs.com/xgtao/p/5985066.html
Copyright © 2020-2023  润新知