zoukankan      html  css  js  c++  java
  • AC日记——Little Elephant and Shifts codeforces 221e

    E - Little Elephant and Shifts

    思路:

      一次函数线段树(疯狂debug);

      b不断循环左移,判断每次最小的|i-j|,a[i]=b[j];

      仔细观察发现,每个bi移动时,|i-j|呈现多个一次函数图像;

      所以用线段树来维护这些一次函数图像;

      线段树维护一次函数,当两个函数在区间没有交点时;

      判断哪个在图像较下的位置,然后覆盖;

      当有交点时,保留最优,将另一条传下去;

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

    代码:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 100005
    #define INF 0x7fffffff
    
    struct TreeNodeType {
        int l,r,k,b,mid;
        
        bool if_;
    };
    struct TreeNodeType tree[maxn<<2];
    
    int n,ai[maxn],p[maxn],X;
    
    inline void in(int &now)
    {
        char Cget=getchar();now=0;
        while(Cget>'9'||Cget<'0') Cget=getchar();
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
    }
    
    void tree_build(int now,int l,int r)
    {
        tree[now].l=l,tree[now].r=r,tree[now].mid=l+r>>1;
        if(l==r) return ;
        tree_build(now<<1,l,tree[now].mid);
        tree_build(now<<1|1,tree[now].mid+1,r);
    }
    
    double com(int k1,int b1,int k2,int b2)
    {
        if(k1==k2) return 0;
        return (double)(b2-b1)/(double)(k1-k2);
    }
    
    void tree_down(int now,int k,int b)
    {
        if(!tree[now].if_)
        {
            tree[now].if_=true,tree[now].k=k,tree[now].b=b;
            return ;
        }
        double x=com(k,b,tree[now].k,tree[now].b);
        if(x<=tree[now].l||x>=tree[now].r)
        {
            double mid=(double)(tree[now].l+tree[now].r)/2;
            if(mid*k+b<mid*tree[now].k+tree[now].b) tree[now].k=k,tree[now].b=b;
            return ;
        }
        if(x<=tree[now].mid)
        {
            if(k>tree[now].k) tree_down(now<<1,k,b);
            else
            {
                tree_down(now<<1,tree[now].k,tree[now].b);
                tree[now].k=k,tree[now].b=b;
            }
        }
        else
        {
            if(k<tree[now].k) tree_down(now<<1|1,k,b);
            else
            {
                tree_down(now<<1|1,tree[now].k,tree[now].b);
                tree[now].k=k,tree[now].b=b;
            }
        }
    }
    
    void tree_add(int now,int l,int r,int k,int b)
    {
        if(tree[now].l==l&&tree[now].r==r)
        {
            if(tree[now].if_)
            {
                if(k==tree[now].k&&b==tree[now].b); 
                else tree_down(now,k,b);
            }
            else tree[now].if_=true,tree[now].k=k,tree[now].b=b;
            return ;
        }
        if(l>tree[now].mid) tree_add(now<<1|1,l,r,k,b);
        else if(r<=tree[now].mid) tree_add(now<<1,l,r,k,b);
        else
        {
            tree_add(now<<1,l,tree[now].mid,k,b);
            tree_add(now<<1|1,tree[now].mid+1,r,k,b);
        }
    }
    
    void tree_query(int now,int to)
    {
        if(tree[now].if_) X=min(X,tree[now].k*to+tree[now].b);
        if(tree[now].l==tree[now].r) return ;
        if(to<=tree[now].mid) tree_query(now<<1,to);
        else tree_query(now<<1|1,to);
    }
    
    int main()
    {
        in(n);int pos,debug;
        for(int i=1;i<=n;i++) in(ai[i]);
        for(int i=1;i<=n;i++) in(pos),p[pos]=i;
        tree_build(1,1,n);
        for(int i=1;i<=n;i++)
        {
            if(i<p[ai[i]])
            {
                tree_add(1,1,p[ai[i]]-i+1,-1,p[ai[i]]+1-i);
                if(i!=1) tree_add(1,p[ai[i]]-i+2,p[ai[i]],1,i-p[ai[i]]-1);
                if(p[ai[i]]!=n) tree_add(1,p[ai[i]]+1,n,-1,n-i+p[ai[i]]+1);
            }
            if(i>p[ai[i]])
            {
                tree_add(1,1,p[ai[i]],1,i-p[ai[i]]-1);
                tree_add(1,p[ai[i]]+1,p[ai[i]]+n-i+1,-1,n-i+p[ai[i]]+1);
                if(i-p[ai[i]]>1) tree_add(1,p[ai[i]]+n-i+2,n,1,i-n-p[ai[i]]-1);
            }
            if(i==p[ai[i]])
            {
                tree_add(1,1,i,1,-1);
                if(i!=n) tree_add(1,i+1,n,-1,n+1);
            }
        }
        for(int i=1;i<=n;i++) X=INF,tree_query(1,i),printf("%d
    ",X);
        return 0;
    }
  • 相关阅读:
    【题解】SDOI2015序列统计
    【合集】有标号的DAG图计数(合集)
    【题解】有标号的DAG计数4
    【题解】有标号的DAG计数3
    【题解】有标号的DAG计数2
    【题解】有标号的DAG计数1
    【题解】歌唱王国(概率生成函数+KMP)+伦讲的求方差
    【题解】CTS2019珍珠(二项式反演+卷积)
    【题解】餐巾计划问题
    【题解】数字梯形问题
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6839306.html
Copyright © 2011-2022 走看看