P1091环城旅行 - 数据结构(模拟题)

P1091环城旅行
标签: [显示标签]

背景

经过若干年的努力,Matrix67终于追到了自己喜爱的MM。他计划带她去一次环城旅行。

描述

Matrix67要带他的女友进行一次环城旅行。他选择了一条总长度为L的封闭路线。他所选择的路线上有n个景点。他将从某个景点出发,顺时针开车绕城市一周,再回到出发点。出发前,油箱为空。每个景点内都有一个加油站,第i个景点的加油站提供的油可供车行驶Si的路程。所有加油站可提供的油的总和恰好够汽车行驶一周(即S1+S2+…+Sn=L)。汽车的油箱总能够容下所得到的汽油。临行前的那一天,Matrix67突然意识到,虽然所有加油站的油的总和等于汽车环城一周要消耗的油,但汽车不一定能环城一周,因为有可能还没有到下一个景点,汽油就用光了。显然,是否会发生半路上没油的情况取决于Matrix67选择的出发点。他可不希望和MM的这次浪漫的旅行就这样泡汤了。他知道每个景点离它前一个景点有多远,也知道每个景点的加油站提供的油量。他希望你能帮助他找出,从哪些景点出发可以顺利绕城一周。

格式

输入格式

第一行为两个正整数,分别代表n和L。输入数据保证n<=500 000,L<=100 000 000,并且n<=L。

第二行到第n+1行这n行数据将按环行道路上顺时针的顺序依次描述各个景点。每行有两个正整数。第i+1行为Di和Si,分别表示第i个景点离其前一个景点(即第i-1个景点)的距离和这个景点的加油站所提供的油可供汽车行驶的距离。其中,D1=0。最后一个(第n个)景点与第一个景点之间的距离没有直接给出,但可以根据输入数据计算出来。

输入数据保证,所有的Si之和等于L,所有的Di之和小于L。

输出格式

一行正整数。输出时,每两个正整数之间都有一个空格,行末无空格。它们表示所有能够作为出发点顺利完成环城旅行的景点。

当存在多个这样的景点时,请按照升序排列输出他们的序号。

当不存在这样的景点时,输出-1。

样例1

样例输入1[复制]

5 10
0 1
2 2
3 2
2 2
2 3

样例输出1[复制]

3 4 5

限制

各个测试点1s

来源

Matrix67 根据经典问题改编

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <vector>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;


#define pb push_back
#define mp make_pair
#define fillchar(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r


typedef long long LL;
typedef pair<int, int > PII;
typedef unsigned long long uLL;
template<typename T>
void print(T* p, T* q, string Gap = " ") {
    int d = p < q ? 1 : -1;
    while(p != q) {
        cout << *p;
        p += d;
        if(p != q) cout << Gap;
    }
    cout << endl;
}
template<typename T>
void print(const T &a, string bes = "") {
    int len = bes.length();
    if(len >= 2)cout << bes[0] << a << bes[1] << endl;
    else cout << a << endl;
}

const int INF = 0x3f3f3f3f;
const int MAXM = 2e5;
const int MAXN = 5e5 + 5;
int s[MAXN],d[MAXN];
int XCY[MAXN];
int main () {
    int n, L;
    bool success;
    while(~scanf("%d%d", &n, &L)) {
        int sum = 0,success = false;
        for(int i = 1; i <= n; i ++) {
            scanf("%d%d", &d[i - 1], &s[i]);
            sum += d[i - 1];
        }
        d[n] = L - sum;
        int Min = INF, C = 0;
        for(int i = 1;i <= n;i ++){
            XCY[i] = s[i] - d[i];
            C += XCY[i];
            Min = min(Min,C);
        }
        for(int i = 1;i <= n;i ++){
            Min -= XCY[i - 1];
            if(Min >= 0){if(success) printf(" ");success = true;printf("%d",i);}
        }
        if(!success)printf("%d",-1);
        puts("");
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值