제출 #1362537

#제출 시각아이디문제언어결과실행 시간메모리
1362537kookeudasLegendary Dango Eater (JOI26_dango)C++20
100 / 100
1307 ms288512 KiB
#include <bits/stdc++.h>
#include <cassert>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;
using ll = long long;
ll n,Q,k;
ll ar[500002];
ll s[500002];
ll sp[500002];
int nxt[500002];
vector<ll> comp;
int seg[4000002];
vector<int> inv[1500002];
vector<int> outv[1500002];
vector<int> pv[1500002];
int d[500002][22];
ll sd[500002][22];
int Upd(int node, int nL, int nR, int idx, int val){
    if(nL>idx || nR<idx)return seg[node];
    if(nL==nR)return seg[node] = min(seg[node],val);
    int mid = (nL+nR)/2;
    return seg[node] = min(Upd(node*2,nL,mid,idx,val),Upd(node*2+1,mid+1,nR,idx,val));
}
int Query(int node, int nL, int nR, int l, int r){
    if(nL>r || nR<l)return n;
    if(l<=nL && nR<=r)return seg[node];
    int mid = (nL+nR)/2;
    return min(Query(node*2,nL,mid,l,r),Query(node*2+1,mid+1,nR,l,r));
}
int ii(ll x){
    return lower_bound(comp.begin(),comp.end(),x)-comp.begin();
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n>>Q>>k;
    for(int i=1;i<=n;i++)cin>>ar[i];
    for(int i=1;i<=n;i++){
        if(i%2==1)s[i] = s[i-1]+ar[i];
        else s[i] = s[i-1]-ar[i];
    }
    for(int i=1;i<=n;i++)sp[i] = s[i]%k;
    for(int i=1;i<=n;i++)if(sp[i]<0)sp[i]+=k;
/*    for(int i=1;i<=n;i++){
        if(i%2==1){
            nxt[i] = n+1;
            for(int j=i+1;j<=n;j+=2){
                if(k-sp[i-1]<=ar[j]-sp[j-1] || (sp[j-1]-ar[j]<=sp[i-1] && sp[i-1]<=sp[j-1])){
                    nxt[i] = j+1;
                    break;
                }
            }
            cout<<nxt[i];
        }
    }*/
    for(int i=1;i<=n;i++){
        comp.push_back(ar[i]-sp[i-1]);
        comp.push_back(k-sp[i-1]);
    }
    comp.push_back(k-sp[n]);
    for(int i=0;i<=4e6;i++)seg[i] = n;
    sort(comp.begin(),comp.end());
    comp.erase(unique(comp.begin(),comp.end()),comp.end());
    for(int i=n;i>=1;i--){
        if(i%2==0){
            Upd(1,0,2*n,ii(ar[i]-sp[i-1]),i);
        }
        else{
            nxt[i] = Query(1,0,2*n,ii(k-sp[i-1]),2*n)+1;
        }
    }
    comp.clear();
    for(int i=1;i<=n;i++){
        comp.push_back(sp[i-1]-ar[i]);
        comp.push_back(sp[i-1]);
        comp.push_back(sp[i-1]+1);
    }
    sort(comp.begin(),comp.end());
    comp.erase(unique(comp.begin(),comp.end()),comp.end());
    for(int i=1;i<=n;i+=2){
        pv[ii(sp[i-1])].push_back(i);
    }
    for(int i=2;i<=n;i+=2){
        inv[ii(sp[i-1]-ar[i])].push_back(i);
        outv[ii(sp[i-1]+1)].push_back(i);
    }
    set<int> ss;
    ss.insert(n+1);
    for(int i=0;i<comp.size();i++){
        for(int ele:inv[i]){
            ss.insert(ele);
        }
        for(int ele:outv[i])ss.erase(ele);
        for(int ele:pv[i]){
            nxt[ele] = min(nxt[ele],*(ss.lower_bound(ele))+1);
        }
    }
/*    for(int i=1;i<=n;i+=2)cout<<nxt[i];*/
    nxt[n+1] = n+1;
    for(int i=1;i<=n+1;i++){
        d[i][0] = nxt[i];
        sd[i][0] = max((ll)0,s[nxt[i]-2]-s[i-1])/k;
    }
    for(int i=1;i<20;i++){
        for(int j=1;j<=n+1;j++){
            d[j][i] = d[d[j][i-1]][i-1];
            sd[j][i] = sd[j][i-1]+sd[d[j][i-1]][i-1];
        }
    }
    while(Q--){
        int l,r;
        cin>>l>>r;
        if(l%2==0)l++;
        if(r%2==0)r--;
        if(l>r){
            cout<<0<<'\n';
            continue;
        }
        /*int cur = l;
        ll ans = 0;
        while(true){
            int nc = nxt[cur];
            if(nc<=r)ans+=(s[nc-2]-s[cur-1])/k;
            else{
                ans+=(s[r]-s[cur-1])/k;
                break;
            }
            cur = nc;
        }*/
        ll ans = 0;
        int cur = l;
        for(int i=19;i>=0;i--){
            if(d[cur][i]<=r){
                ans += sd[cur][i];
                cur = d[cur][i];
            }
        }
        ans+=(s[r]-s[cur-1])/k;
        cout<<ans<<'\n';
    }
    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…