1. 程式人生 > >2018 ICPC Asia Beijing Regional Contest 北京網路賽D. 80 Days

2018 ICPC Asia Beijing Regional Contest 北京網路賽D. 80 Days

傳送門

北京網路賽我們隊只做出了這道題。賽後學校將現場賽隊伍進行了調整,其中兩個能穩穩參加現場賽的隊伍發揮很不好,一個爆零一個差點爆零,錯失最後一次機會。我們隊雖然之前也拿過一次倒一拿過一次倒三,但是憑藉其它場次前十名的穩定發揮,讓已經跌倒谷底的平均排名緩緩上升,再加上北京網賽的順利一A,以女隊身份拿到最後一個確定的南京站名額(雖然很想去北京)。“可怕”的北京網賽。總結一下,有另外兩位隊友的貢獻和配合,再加上不因為曾經的重大失誤而放棄之後的比賽,是我們最後獲得穩定名額的原因。小菜雞以後要多努力,不要讓自己再處於這種危險的緊急邊緣了。

題意:

n個城市環形連線,初始有c的錢,每到i城市,會獲得a[i]的金錢,失去b[i]的金錢,問能否走遍這n個城市,且過程中金錢不為負數,輸出起始城市,如果答案有多個,輸出最小的數字。

思路:

a[i]-b[i]的值就是到達第i個城市的金錢變化。最開始想到暴力列舉起點城市,模擬後續到其他城市的金錢變化,出現負數就break,但是100個樣例,1e6的資料,總共1e8的資料感覺一定會超時,於是20分鐘寫好的暴力程式碼就放在那了,不敢交。之後參考https://blog.csdn.net/ac_0_summer/article/details/47074001 用單調佇列做的。1A。(感謝小寶貝的搜題能力)

賽後發現單調佇列246ms和暴力532ms都能過。。。資料太水

附上兩種程式碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int a[2000009];
int q[1000010];
int n;
int head,rear;

void pushq(int i)
{
	while(head<=rear&&a[q[rear]]>=a[i]) rear--;
    q[++rear]=i;
}
void popq(int i)
{
	while(q[head]<i-n+1) head++;
}
int main()
{

    int t;cin>>t;
    while(t--)
    {
        head=0;rear=-1;
        int 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<=2*n;i++) a[i]+=a[i-1];
        //for(int i=1;i<=2*n;i++) cout<<a[i]<<" "; cout<<endl;
        for(int i=1;i<n;i++) pushq(i);
        int i;
		for(i=n;i<2*n;i++){
			pushq(i);
			popq(i);
			if(a[q[head]]-a[i-n]>=-c){
                flag=1;
                break;
			}
		}
        if(flag) printf("%d\n",i-n+1);
        else printf("-1\n");
    }
}

#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");
    }
}