80 Days (尺取法)

80 Days is an interesting game based on Jules Verne's science fiction "Around the World in Eighty Days". In this game, you have to manage the limited money and time.

Now we simplified the game as below:

There are n cities on a circle around the world which are numbered from 1 to n by their order on the circle. When you reach the city i at the first time, you will get ai dollars (ai can even be negative), and if you want to go to the next city on the circle, you should pay bi dollars. At the beginning you have c dollars.

The goal of this game is to choose a city as start point, then go along the circle and visit all the city once, and finally return to the start point. During the trip, the money you have must be no less than zero.

Here comes a question: to complete the trip, which city will you choose to be the start city?

If there are multiple answers, please output the one with the smallest number.

输入

The first line of the input is an integer T (T ≤ 100), the number of test cases.

For each test case, the first line contains two integers n and c (1 ≤ n ≤ 106, 0 ≤ c ≤ 109).  The second line contains n integers a1, …, an  (-109 ≤ ai ≤ 109), and the third line contains n integers b1, …, bn (0 ≤ bi ≤ 109).

It's guaranteed that the sum of n of all test cases is less than 106

输出

For each test case, output the start city you should choose.

提示

For test case 1, both city 2 and 3 could be chosen as start point, 2 has smaller number. But if you start at city 1, you can't go anywhere.

扫描二维码关注公众号,回复: 4632953 查看本文章

For test case 2, start from which city seems doesn't matter, you just don't have enough money to complete a trip.

样例输入

2
3 0
3 4 5
5 4 3
3 100
-3 -4 -5
30 40 50

样例输出

2
-1

题意:t组数据,每组数据中有n个城市组成一个环,刚开始有c元。紧跟的一行代表可以在每个城市挣得钱数a[i](可为负数),之后一行代表在每个城市花费的钱数b[i]。求可以从哪个城市开始旅行,中途自身的钱数不能小于0,且能回到起点。不能的话输出-1.

思路:先计算出在每个城市的收入c[i](c[i]=a[i]-b[i]).然后用尺取法开始找点: 先找一个左指针k 指向第一个数,并假设它为起点,然后右指针依次让后走计算当前和sum,当sum<0时,代表此时在中途钱数小于0了,既起点不满足方案,因此我们把左指针向左依次移动,知道sum>=0时停止,然后继续走右指针。因为是一个环,那么当右指针走到终点时,需要重新返回到起点,继续判断。那右指针再次和左指针重合的时候,说明以左指针为起点的这条路径可行,输出左指针的索引。  当左指针已经到达n,且不满足条件的时候,说明没有满足条件的路径。

代码如下:

#include<cstdio>
#include<cstring>
#define LL long long
#define N 1000010
LL a[N],b[N],c[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            scanf("%lld",&a[i]);
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&b[i]);
            c[i]=a[i]-b[i];  //计算此点的收入
        }
        LL sum=m;//初始化金钱数
        int k=0;//k为左指针,并假设k为起点
        //只有n个城市,起点最多只能从第n个城市开始
        for(int i=1; i<=n; i++)  //i为右指针
        {
            sum+=c[i]; //计算和
            if(sum<0) //当和小于0时,说明此时的起点不能满足条件,需要往右移
            {
                while(sum<0&&k<=n)  //找到当前满足条件的起点
                    sum-=c[++k];
            }
        }
        for(int i=1; i<=k; i++)  //因为是个环,终点肯定在左指针k处,k为动态的,最大为n
        {
            sum+=c[i];
            if(sum<0)
            {
                while(sum<0&&k<=n)  //起点右移
                {
                    sum-=c[++k];
                    if(k>n)
                        break;
                }
            }
            if(k>n)
                break;
        }
        if(k<=n)  //找到了一条路
            printf("%d\n",k+1);
        if(k>n)
            printf("-1\n");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41890797/article/details/82819900