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 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)