zoukankan      html  css  js  c++  java
  • [CF1295E] Permutation Separation

    Description

    给定一个长度为 (n) 的排列,你可以将它切成两段 (A,B),分别作为两个集合,对于第 (i) 个元素,可以花费 (a[i]) 的代价把它移动到对面的集合中。求至少花费多少的代价,才能使得一个集合中的任意元素比另一个集合中的任意元素小。

    Solution

    枚举初态分界点 (pos) 和分界值 (val),设此时的答案为 (f(pos,lim)),暴力计算的话复杂度为 (O(n^2))

    考虑到 (f(pos,lim)-f(pos-1,lim)=sum_{lim < p_{pos}} a_{pos} - sum_{lim ge p_{pos}} a_{pos}),我们用线段树来维护对于某个确定的 (pos) 的所有 (f(pos,lim)),每次修改 (pos) 时,只需要将 (1 le lim < p_{pos}) 部分 (+a_{pos}),将 (p_{pos} le lim le n) 部分 (-a_{pos})。区间修改,区间询问最小值。

    特别注意,lim 是可以 =0 的。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    struct SegmentTree 
    {
        int a[N],tag[N];
        void Pushup(int p)
        {
            a[p]=min(a[p*2],a[p*2+1]);
        }
        void Put(int p,int val)
        {
            a[p]+=val;
            tag[p]+=val;
        }
        void Pushdown(int p)
        {
            if(tag[p])
            {
                Put(p*2,tag[p]);
                Put(p*2+1,tag[p]);
                tag[p]=0;
            }
        }
        void Modify(int p,int l,int r,int ql,int qr,int val)
        {
            if(l>qr||r<ql) return;
            if(l>=ql&&r<=qr)
            {
                Put(p,val);
            }
            else 
            {
                Pushdown(p);
                Modify(p*2,l,(l+r)/2,ql,qr,val);
                Modify(p*2+1,(l+r)/2+1,r,ql,qr,val);
                Pushup(p);
            }
        }
        int Query()
        {
            return a[1];
        }
    } seg;
    
    int n,a[N],b[N],p[N],f[N];
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>p[i];
        for(int i=1;i<=n;i++) cin>>a[i];
    
        for(int i=1;i<=n;i++) 
        {
            // cerr<<"Modify "<<p[i]<<" "<<n<<" "<<a[i]<<endl;
            seg.Modify(1,0,n,p[i],n,a[i]);
        }
        int ans=1e18;
        for(int i=1;i<n;i++)
        {
            seg.Modify(1,0,n,0,p[i]-1,a[i]);
            seg.Modify(1,0,n,p[i],n,-a[i]);
            ans=min(ans,seg.Query());
        }
        cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    ci框架——文章查看之上篇下篇
    ci框架——分页
    ci框架——数据库(增删改查)
    全选和反选
    基于CI框架的管理系统
    在dedecms系统下, 改写火车头的入库接口 写一个接口文件运行一次自动读取 http://news.163.com/rank/
    缩略图
    php——两种无限级分类
    webpack和webpack-dev-server安装配置(遇到各种问题的解决方法)
    python装饰器
  • 原文地址:https://www.cnblogs.com/mollnn/p/14037993.html
Copyright © 2011-2022 走看看