• ZJOI 2018 Day 2 胖


    考试的时候刚了很久.

    还是没做出来.

    看完了题解才恍然大悟.

    贴一发丑陋的两个log常数巨大代码

    #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
    ",ans);
        }
    }
    View Code

    感觉这题应该是可以一个log做的,

    就是有些难写,需要仔细考虑一下.

  • 相关阅读:
    bzoj 1196: [HNOI2006]公路修建问题 二分+并查集
    bzoj 1607: [Usaco2008 Dec]Patting Heads 轻拍牛头 筛法
    bzoj 1050: [HAOI2006]旅行comf 并查集
    bzoj 1040: [ZJOI2008]骑士 树形dp
    bzoj 1295: [SCOI2009]最长距离
    bzoj 1070: [SCOI2007]修车 费用流
    bzoj 1057: [ZJOI2007]棋盘制作 单调栈
    bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配
    sass/scss 和 less的区别
    IONIC实现图片轮播
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/8969846.html
Copyright © 2020-2023  润新知