ZJOI 2018 Day 2 胖

It's been a long time since the exam.

Still haven't made it.

After reading the solution, I realized it.

Post an ugly two log constant huge code

#include <bits/stdc++.h>
using namespace std;
const int N=200010;
const long long INF=1e18;
int n,m,k,lg[N];
long long s[N],f[N][18],g[N][18];
pair<int,int> a[N];
void UPD(int i,int j,long long r[N][18]){
    r[i][j]=(i+(1<<(j-1))<=k?min(r[i][j-1],r[i+(1<<(j-1))][j-1]):r[i][j-1]);
}
long long ask(int x,int y,long long r[N][18]){
    return x>y?INF:min(r[x][lg[y-x+1]],r[y-(1<<lg[y-x+1])+1][lg[y-x+1]]);
}
long long hhdask(int x,int y,int dpos){
    if (x>y) return INF;
    int be=lower_bound(a+1,a+k+1,make_pair(x,0))-a;
    int en=lower_bound(a+1,a+k+1,make_pair(y+1,0))-a-1;
    int mid=lower_bound(a+1,a+k+1,make_pair(dpos,0))-a;
    long long rmin=ask(mid,en,f)-s[dpos-1];
    long long lmin=ask(be,mid-1,g)+s[dpos-1];
    return min(lmin,rmin);
}
bool check(int x,int e,long long v,int po){//close interval
    long long t=hhdask(x-e+po,x+e+po-1,x);
    if (!po||t!=v) return t>v;
    return hhdask(x-e+1,x+e-1,x)>v;
}
signed main(){
    lg[1]=0; for (int i=2; i<=200000; ++i) lg[i]=lg[i>>1]+1;
    scanf("%d%d",&n,&m);
    for (int i=1; i<n; ++i){
        int x; scanf("%d",&x);
        s[i]=s[i-1]+x;
    }
    for (int i=1; i<=m; ++i){
        long long ans=0;
        scanf("%d",&k);
        for (int i=1; i<=k; ++i) scanf("%d%d",&a[i].first,&a[i].second);
        sort(a+1,a+k+1);
        for (int i=1; i<=k; ++i) f[i][0]=a[i].second+s[a[i].first-1],g[i][0]=a[i].second-s[a[i].first-1];
        for (int i=1; i<18; ++i)
        for (int j=1; j<=k; ++j)
        UPD (j, i, f), UPD (j, i, g);
        for (int i=1; i<=k; ++i){
            //find l limit
            int ll=a[i].first,rr=a[i].first;
            for (int l=1,r=a[i].first,mid=(l+r)>>1; l<=r; mid=(l+r)>>1)
            if (check(mid,a[i].first-mid,a[i].second+s[a[i].first-1]-s[mid-1],0)) ll=mid,r=mid-1; else l=mid+1;
            //find r limit
            for (int l=a[i].first,r=n,mid=(l+r)>>1; l<=r; mid=(l+r)>>1)
            if (check(mid,mid-a[i].first,a[i].second+s[mid-1]-s[a[i].first-1],1)) rr=mid,l=mid+1; else r=mid-1;
            ans+=rr-ll+1;
        }
        printf("%lld\n",ans);
    }
}
View Code

I feel that this question should be able to be done with a log,

It's a bit difficult to write, and needs to be carefully considered.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325023596&siteId=291194637