Zerojudge f581

首次架設靜態網站,如有疏失,還請多多包涵。歡迎來信zhuastor@gmail.com

解題心得

算是我對於D&C部分的第一次小推導
其實沒有很難,希望在APCS的時候也能如此發揮
不過老實說我一開始並沒有想到用二分搜
是在後來看到(n<=200000)才驚覺一般搜尋估計會TLE

解題想法

我使用Lower_bound搭配前綴和(累加)
還有一個變數代表現在是第幾項(now)
說白了就是把一個陣列模擬包裝的概念罷了
(習慣開long long int 版面醜很抱歉)
Lower_bound的部分是本題我的解題關鍵
只需要二分搜索求元素扣掉當前位置(now)的前一個元素(因為累加,所以可以得到這段區間的和)
至於二分搜的形式有好多種,關鍵觀念不要偏就好
比較需要注意的是可以自己想想看
使用陣列模擬的情況下,回到開頭的各變數修改(小麻煩)

AC code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll int n,m,now=0,p,g;
ll int a[200005],ans=0;
ll int lower_bound(ll int left,ll int right,ll int goal){
    ll int mid,pos,ps=0;
    bool ta=true;
    if(left!=0){
        ps=a[left-1];
    }
    while(left<right){
        mid=(left+right)/2;
        if((a[mid]-ps)==goal){
            pos=mid;
            ta=false;
            break;
        }
        else if((a[mid]-ps)>goal){
            // too right
            right=mid;
            ta=false;
            pos=right;
        }
        else{
            left=mid+1;
            pos=left;
        }
    }
    if(ta){
        return lower_bound(0,right,goal-(a[right-1]-ps));
    }
    else{
        return pos;
    }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin >> n >> m;
    for(int x=0;x<n;x++){
        cin >> a[x];
        ans+=a[x];
        a[x]=ans;
    }
    while(m--){
        cin >> p;
        g=lower_bound(now,n,p);
        now=(g+1)%n;
    }
    cout << now << endl;
    return 0;
}

題目連結 : 2020年7月APCS 3.圓環出口