• CF765F Souvenirs


    考虑将询问离线,固定右端点 (i),这里只考虑满足 (j<i,a_j>a_i) 的答案,因为将 (a_i) 的值域翻转后再做一遍就能得到所有情况。询问就是查询对于每个位置 (j) 得到的答案的后缀最小值。

    用权值线段树就能找到满足 (j<i,a_j>a_i) 的最大位置 (j),但一个一个往前跳找出所有的位置 (j),复杂度无法接受,还需进一步优化。

    考虑当前位置为 (j),要想下一次找到的位置 (j') 能更新答案,其必须满足 (a_{j'}-a_i<a_j-a_{j'}),因为位置 (j') 更新过位置 (j),要更新后缀最小值就必须满足这个式子。移项得 (a_{j'}-a_i<frac{1}{2}(a_j-a_i)),发现差值每次减半,设值域为 (V),因此在限制下往前跳的合法位置个数为 (O(log V))。答案用树状数组维护后缀最小值即可。

    复杂度为 (O(n log^2 V))

    #include<bits/stdc++.h>
    #define maxn 300010
    #define maxm 10000010
    #define all 1000000000
    #define mid ((l+r)>>1)
    #define lowbit(x) (x&(-x))
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,tot,root;
    int a[maxn],ans[maxn],t[maxn],ls[maxm],rs[maxm],mx[maxm];
    vector<pair<int,int> > ve[maxn];
    void update(int x,int v)
    {
        while(x) t[x]=min(t[x],v),x-=lowbit(x);
    }
    int ask(int x)
    {
        int v=all;
        while(x<=n) v=min(v,t[x]),x+=lowbit(x);
        return v;
    }
    void modify(int l,int r,int pos,int v,int &cur)
    {
        if(!cur) cur=++tot;
        mx[cur]=max(mx[cur],v);
        if(l==r) return;
        if(pos<=mid) modify(l,mid,pos,v,ls[cur]);
        else modify(mid+1,r,pos,v,rs[cur]);
    }
    int query(int L,int R,int l,int r,int cur)
    {
        if(!cur) return 0;
        if(L<=l&&R>=r) return mx[cur];
        int v=0;
        if(L<=mid) v=max(v,query(L,R,l,mid,ls[cur]));
        if(R>mid) v=max(v,query(L,R,mid+1,r,rs[cur]));
        return v;
    }
    void clear()
    {
        for(int i=1;i<=n;++i) t[i]=all;
        for(int i=1;i<=tot;++i) ls[i]=rs[i]=mx[i]=0;
        tot=root=0;
    }
    void work()
    {
        clear();
        for(int i=1;i<=n;++i)
        {
            int pos=query(a[i],all,0,all,root);
            while(pos)
            {
                update(pos,a[pos]-a[i]);
                pos=query(a[i],(a[i]+a[pos])/2-(~(a[i]+a[pos])&1),0,all,root);
            }
            modify(0,all,a[i],i,root);
            for(int j=0;j<ve[i].size();++j)
                ans[ve[i][j].second]=min(ans[ve[i][j].second],ask(ve[i][j].first));
        }
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;++i) read(a[i]);
        read(m);
        for(int i=1;i<=m;++i)
        {
            int l,r;
            read(l),read(r),ans[i]=all;
            ve[r].push_back({l,i});
        }
        work();
        for(int i=1;i<=n;++i) a[i]=all-a[i];
        work();
        for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Android开发探秘之一:创建可以点击的Button
    TCP之心跳包实现思路
    Asp.net与Dojo交互:仪器仪表实现
    Asp.net Json数据解析的一种思路
    Asp.net通过Jquery操作WebService进行Ajax读写
    GridView自定义删除操作
    从客户端中检测到有潜在危险的request.form值
    JUC-Condition线程通信
    ModelAndView 配置与使用
    SpringMVC之ModelAndView的用法(转)
  • 原文地址:https://www.cnblogs.com/lhm-/p/13795125.html
Copyright © 2020-2023  润新知