Codeforces 1295E. Permutation Separation (线段树)

https://codeforces.com/contest/1295/problem/E

建一颗线段树,叶子结点是花费从1到i所需要花费的前缀和,表示前i个元素全部移动到右边的花费,再维护区间最小值,然后从1到n-1扫一遍,对于第i个位置,找到数字i在序列中的位置 pos ,将区间1到pos-1加上数字i移动的花费,pos到n-1减去数字i移动的花费,因为位置大于等于i 的时候,不需要将数字i移动到右边,位置小于i 时,需要把数字i移动到左边,所以需要增加数字i的花费,结合线段树维护的是前缀和数组,那么对于每一个位置i 用线段树维护的最小值去更新答案ans即可。

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const int maxn = 2e5+5;
 5 ll pos[maxn],cost[maxn],a[maxn],sum[maxn];
 6 struct segT{
 7     ll l,r;
 8     ll dat,lz;
 9 }t[maxn*4];
10 void build(ll p,ll l,ll r){
11     t[p].l = l,t[p].r = r;
12     if(l == r) { t[p].dat = sum[l] ,t[p].lz = 0;return;}
13     ll mid = (l+r)/2;
14     build(p*2,l,mid);
15     build(p*2+1,mid+1,r);
16     t[p].dat = min(t[p*2].dat ,t[p*2+1].dat );
17 }
18 void upd(ll p,ll L,ll R,ll v){
19     if(t[p].l >= L&&t[p].r <= R ) {t[p].dat += v,t[p].lz +=v;return;}
20     if (t[p].lz && L!=R ) {
21     t[p * 2].dat += t[p].lz ,t[p*2+1].dat +=t[p].lz  ;
22     t[p * 2].lz  += t[p].lz ,t[p*2+1].lz += t[p].lz;  
23     t[p].lz = 0;                             
24     }
25     int mid = (t[p].l + t[p].r )/2;
26     if(L<=mid) upd(p*2,L,R,v);
27     if(R>mid) upd(p*2+1,L,R,v);
28     t[p].dat = min(t[p*2].dat ,t[p*2+1].dat );
29 }
30 int query(ll p,ll l,ll r){
31     if(l<=t[p].l && r>=t[p].r ) return t[p].dat ;
32     int mid = (t[p].l + t[p].r )/2;
33     int val = 0x3f3f3f3f;
34     if(l<=mid) val = min(val,query(p*2,l,r));
35     if(r>mid)  val = min(val,query(p*2+1,l,r));
36     return val;
37 }
38 int main()
39 {
40     int n;
41     scanf("%d",&n);
42     for(int i = 1;i<=n;i++) {
43         scanf("%lld",&a[i]);
44         pos[a[i]] = i;
45     }
46     for(int i = 1;i<=n;i++){
47         scanf("%lld",&cost[i]);
48         sum[i] = sum[i-1] + cost[i];
49     }
50     build(1,1,n-1);
51     ll ans = cost[n];
52     ans = min(ans,t[1].dat );
53     for(int i = 1;i<=n;i++){
54         if(pos[i]!=n) upd(1,pos[i],n-1,-cost[pos[i]]);
55         if(pos[i]!=1) upd(1,1,pos[i]-1,cost[pos[i]]);
56         ans = min(ans,t[1].dat);
57     }
58     printf("%lld",ans);
59     return 0;
60 }

 

上一篇:WangDeLiangReview2018 - (1)引入


下一篇:Range of int, long, 和 long long 的数值范围