zoukankan      html  css  js  c++  java
  • 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 ",i); else printf("-1 "); } }

    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
    ",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
    ",q.front());
    52                         f=1;
    53                         break;
    54                     }
    55                 }
    56             }
    57         }
    58         if(f==0) printf("-1
    ");
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    回流与重绘
    事件循环的一些小啰嗦
    async与await的那些事儿
    数组去重的方法们
    Object的一些常用方法
    JS事件流的一些理解
    关于Ajax的那些记录
    call、bind与apply函数的区别
    继承的一些细碎记载
    计算机基础的小贴士(1)
  • 原文地址:https://www.cnblogs.com/unknownname/p/9693550.html
Copyright © 2011-2022 走看看