zoukankan      html  css  js  c++  java
  • 「ZJOI2018」胖(ST表+二分)

    「ZJOI2018」胖(ST表+二分)

    不开 (O_2) 又没卡过去是种怎么体验。。。

    这可能是 (ZJOI2018) 最简单的一题了。。。我都能 (A)。。。

    首先我们发现这个奇怪的图每个点扩展的是一个区间 ([L,R]),然后我们就可以二分端点了。

    一个点 (x) 扩展到点 (y) 至少要 (|x-y|) 的时间,所以我们把 (a_i) 排个序,在上面二分一个合法的区间使得 (|x-a_l|leq t)(|x-a_r|leq t)

    然后若能扩展到 (y),那么 (0) 号点到 (y) 号点的距离为 (|dis_y-dis_x|+l)。我们用两个 (ST) 表把绝对值拆掉,分别维护最小值即可。

    时间复杂度 (O(nlog^2 n))

    为什么 (dl) 出题人会出到 (2 imes 10^5)。。。两个 (log) 一般只出到 (10^5) 的啊。。。

    (Code Below:)

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=200000+10;
    int n,m,k,w[maxn],lg[maxn];ll dis[maxn];
    
    struct node{
        int p;ll l;
        node(int p=0,ll l=0):p(p),l(l){}
    }a[maxn];
    inline bool operator < (const node &a,const node &b){
        return a.p<b.p;
    }
    
    struct Sparse_Table{
        ll st[maxn][18];
        inline void init(){
            for(int i=1;i<=k;i++) st[i][0]=a[i].l;
            for(int j=1;j<=lg[k];j++)
                for(int i=1;i+(1<<j)-1<=k;i++) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
        inline ll query(int l,int r){
            l=max(l,1);r=min(r,n);
            l=lower_bound(a+1,a+k+1,node(l))-a;
            r=upper_bound(a+1,a+k+1,node(r))-a-1;
            if(l>r) return 1e18;
            int k=lg[r-l+1];
            return min(st[l][k],st[r-(1<<k)+1][k]);
        }
    }L,R;
    
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
    
    
    inline bool check1(int x,int y){
    //	(2*y-x,y,x]
        if(x==y) return 1;
        ll a=L.query(2*y-x+1,y)+dis[y];
        ll b=R.query(y,x-1)-dis[y];
        ll c=R.query(x,x)-dis[y];
        if(a<=c||b<=c) return 0;
        if(2*y-x>=1) return L.query(2*y-x,2*y-x)+dis[y]>=c;
        return 1;
    }
    
    inline bool check2(int x,int y){
    //	[x,y,2*y-x)
        if(x==y) return 1;
        ll a=L.query(x+1,y)+dis[y];
        ll b=R.query(y,2*y-x-1)-dis[y];
        ll c=L.query(x,x)+dis[y];
        if(a<=c||b<=c) return 0;
        if(2*y-x<=n) return R.query(2*y-x,2*y-x)-dis[y]>c;
        return 1;
    }
    
    inline int solve1(int x){
        int l=1,r=x,mid,ans=0;
        while(l<=r){
            mid=(l+r)>>1;
            if(check1(x,mid)) r=mid-1,ans=mid;
            else l=mid+1;
        }
        return ans;
    }
    
    inline int solve2(int x){
        int l=x,r=n,mid,ans=0;
        while(l<=r){
            mid=(l+r)>>1;
            if(check2(x,mid)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        return ans;
    }
    
    int main()
    {
        n=read(),m=read();
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=2;i<=n;i++){
            w[i]=read();
            dis[i]=dis[i-1]+w[i];
        }
        ll ans;
        while(m--){
            k=read();
            for(int i=1;i<=k;i++) a[i].p=read(),a[i].l=read();
            sort(a+1,a+k+1);ans=0;
            for(int i=1;i<=k;i++) a[i].l-=dis[a[i].p];L.init();
            for(int i=1;i<=k;i++) a[i].l+=2*dis[a[i].p];R.init();
            for(int i=1;i<=k;i++) ans+=solve2(a[i].p)-solve1(a[i].p)+1;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Linux基础知识
    redis info
    记录: 解决 pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)
    IOS IAP 自动续订 之 利用rabbitmq延时队列自动轮询检查是否续订成功
    Python3.6 的字典为什么会快
    IAP 订阅后端踩坑总结之 Google 篇
    docker 命令合集
    Python Schema使用说明
    Apache Bench测试
    channels2.X 学习笔记
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10453231.html
Copyright © 2011-2022 走看看