• Educational Codeforces Round 81 (Rated for Div. 2)E(线段树)


    预处理把左集划分为大小为1~i-1时,把全部元素都移动到右集的代价,记作sum[i]。

    然后枚举终态时左集的大小,更新把元素i 留在/移动到 左集的代价。

    树状数组/线段树处理区间修改/区间查询

     1 #define HAVE_STRUCT_TIMESPEC
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 #define ll long long
     5 const int N=2e5+7;
     6 struct Tree{
     7     ll minn,lazy;
     8 }tree[N<<2];
     9 ll sum[N];//前缀和
    10 inline void build(int root,int l,int r){
    11     if(l==r){
    12         tree[root].minn=sum[l];//1~l的a[i]之和
    13         tree[root].lazy=0;
    14         return;
    15     }
    16     int mid=(l+r)>>1;
    17     build((root<<1),l,mid);
    18     build((root<<1|1),mid+1,r);
    19     tree[root].minn=min(tree[(root<<1)].minn,tree[(root<<1|1)].minn);//up
    20     return;
    21 }
    22 inline void pushdown(int root){
    23     if(!tree[root].lazy)
    24         return;
    25     tree[(root<<1)].minn+=tree[root].lazy;
    26     tree[(root<<1|1)].minn+=tree[root].lazy;
    27     tree[(root<<1)].lazy+=tree[root].lazy;
    28     tree[(root<<1|1)].lazy+=tree[root].lazy;
    29     tree[root].lazy=0;
    30     return;
    31 }
    32 inline void change(int root,int l,int r,int x,int y,int val){
    33     if(r<x||l>y)
    34         return;
    35     if(x<=l&&r<=y){
    36         tree[root].minn+=val;
    37         tree[root].lazy+=val;
    38         return;
    39     }
    40     int mid=(l+r)>>1;
    41     pushdown(root);
    42     change((root<<1),l,mid,x,y,val);
    43     change((root<<1|1),mid+1,r,x,y,val);
    44     tree[root].minn=min(tree[(root<<1)].minn,tree[(root<<1|1)].minn);//up
    45     return;
    46 }
    47 int n,p[N],a[N],pos[N];
    48 ll ans;
    49 int main(){
    50     ios::sync_with_stdio(false);
    51     cin.tie(NULL);
    52     cout.tie(NULL);
    53     cin>>n;
    54     for(int i=1;i<=n;++i){
    55         cin>>p[i];
    56         pos[p[i]]=i;//数字p[i]出现的位置为i
    57     }
    58     for(int i=1;i<=n;++i){
    59         cin>>a[i];
    60         sum[i]=sum[i-1]+a[i];//sum[i]为左集合大小为i,把左集合所有元素都移动到右集合的花费
    61     }
    62     build(1,1,n-1);
    63     ans=min(a[1],a[n]);//a[1]为左集为空,a[n]为右集为空
    64     for(int i=1;i<n;++i){//枚举左集大小,定下大小后,集合内元素也被定为1~i
    65         change(1,1,n-1,1,pos[i]-1,a[pos[i]]);//找到元素i出现的位置,在它出现位置左边的sum[i]分别加上把元素i从右集合移动到左集合的代价(原本的sum[1~i-1]为把原本处于位置1~i-1的元素都移动到右边,此时加上元素1~i从右移动到左的代价)
    66         change(1,1,n-1,pos[i],n,-a[pos[i]]);//在它出现位置及其右边的sum[i]分别减去把元素i从左集合移动到右集合的代价(元素i无需移动,可是移动的代价事先已经加到sum[i~n]里了)
    67         ans=min(ans,tree[1].minn);//如果左集大小为i的代价最小就更新最小值
    68     }
    69     cout<<ans;
    70     return 0;
    71 }
    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    C#连接手机安装软件和发送信息
    asp.net 简单分页打印
    asp.net 下载的几种方式
    js 刷新后不提示并保留控件状态
    JAVA 基础编程练习题2 【程序 2 输出素数】
    JAVA 基础编程练习题1 【程序 1 不死神兔】
    setMaxActive和setMaxWait方法
    java.lang.UnsupportedClassVersionError: com/mysql/jdbc/Driver : Unsupported major.minor version 52.0
    java.lang.RuntimeException: org.dom4j.DocumentException: 1 字节的 UTF-8 序列的字节 1 无效。
    HTML DOM firstChild lastChild nextSibling previousSibling 属性_获取属性值的undefined问题
  • 原文地址:https://www.cnblogs.com/ldudxy/p/12244494.html
Copyright © 2020-2023  润新知