ACM-ICPC 2018年北京网络赛 D-80 days

题意: n个城市环形连接,初始有c的钱,每到i城市,会获得a[i]的金钱,失去b[i]的金钱,问能否走遍这n个城市,且过程中金钱不为负数,输出起始城市,如果答案有多个,输出最小的数字。

思路:a[i]-b[i]的值就是到达第i个城市的金钱变化,最开始想到暴力枚举起点城市,模拟后续到其他城市的金钱变化,出现负数就break。但是,100个样例,1e6的数据,总共1e8的数据,感觉如果直接暴力的话,一定会超时,所以果断放弃。接下来便想着只用一重循环就可以解决问题,考虑了很久,发现可以用尺取法优化,但还是wa了。

总结:赛后看题解的时候,暴力可以过,数据太水了。虽然如此,但正确的打开方式是:双端队列 + 尺取法。

双端队列:https://blog.csdn.net/caicai_zju/article/details/49227927

以下附上两种代码:

1.暴力

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int a[2000009]; int main() { int t;cin>>t; while(t--) { int n,c,flag=0; scanf("%d%d",&n,&c); long long sum=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) { int kk;scanf("%d",&kk); a[i]-=kk; a[i+n]=a[i]; } // for(int i=1;i<=n;i++) cout<<a[i]<<endl; int i; for(i=1;i<=n;i++){ int j; for(j=0;j<n;j++){ sum+=a[j+i]; if(c+sum<0) break; } if(j==n) {flag=1;break;} else sum=0; } if(flag) printf("%d\n",i); else printf("-1\n"); } }

2.双端队列+尺取法

 1 #include<bits/stdc++.h>
 2 #define MAX 2000010
 3 using namespace std;
 4 typedef long long ll;
 5 
 6 ll a[MAX],b[MAX];
 7 deque<int> q;
 8 
 9 int main()
10 {
11     int t,n,i,j;
12     ll x;
13     scanf("%d",&t);
14     while(t--){
15         scanf("%d%lld",&n,&x);
16         for(i=1;i<=n;i++){
17             scanf("%lld",&a[i]);
18         }
19         for(i=n+1;i<=n+n;i++){
20             a[i]=a[i-n];
21         }
22         for(i=1;i<=n;i++){
23             scanf("%lld",&b[i]);
24         }
25         for(i=n+1;i<=n+n;i++){
26             b[i]=b[i-n];
27         }
28         while(q.size()){
29             q.pop_back();
30         }
31         int f=0;
32         for(i=1;i<=n+n;i++){
33             if(x+a[i]-b[i]>=0){
34                 x+=a[i]-b[i];
35                 q.push_back(i);
36                 if(q.size()>=n){
37                     printf("%d\n",q.front());
38                     f=1;
39                     break;
40                 }
41             }
42             else{
43                 while(x+a[i]-b[i]<0&&q.size()){
44                     x-=a[q.front()]-b[q.front()];
45                     q.pop_front();
46                 }
47                 if(x+a[i]-b[i]>=0){
48                     x+=a[i]-b[i];
49                     q.push_back(i);
50                     if(q.size()>=n){
51                         printf("%d\n",q.front());
52                         f=1;
53                         break;
54                     }
55                 }
56             }
57         }
58         if(f==0) printf("-1\n");
59     }
60     return 0;
61 }

猜你喜欢

转载自www.cnblogs.com/unknownname/p/9693550.html