Codeforces 1295E.Permutation Separation 线段树

题意

给你一个排列,然后先分成非空的两段(一段是前缀,一段是后缀),然后每挪一个元素到另一端都有一个花费,问最少花费使得前面一段严格小于后面一段

题解

这种题读完题目就应该知道是数据结构,分成两段可以考虑枚举前面一段的最大的数
然后就是要考虑在哪里切,线段树维护分割线

一开始所有数都对该数以后的分割线都有花费(包含就要被挪出去)
后来包含的就不用被挪出去,不包含的还要有花费(分割线不包含的花费增加)

这样把所有分割线的情况考虑了就可以了,线段树维护上述操作

代码

#include <set> 
#include <map>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <vector> 
#include <cstdlib>
#include <cstring>
#include <climits>
#include <complex>
#include <iostream>
#include <algorithm>

#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define dmp(x) cout << (x) << endl;

using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll,ll> pii;

const ll N = 1000010;
const ll mod = 998244353;
const ll inf = 1e15;

inline ll read()
{
  ll p=0; ll f=1; char ch=getchar();
  while(ch<'0' || ch>'9'){if(ch=='-') f*=-1; ch=getchar();}
  while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
  return p*f;
}

ll lc[N<<1],rc[N<<1],lazy[N<<1],c[N<<1]; ll rt,tot;
void build(ll &u,ll L,ll R)
{
  if(!u) u = ++tot;
  if(L==R){c[u] = 0; return ;}
  ll mid = (L+R)>>1;
  build(lc[u],L,mid);
  build(rc[u],mid+1,R);
  c[u] = min(c[lc[u]] , c[rc[u]]);
}
void push_down(ll u)
{
  if(lazy[u])
  {
    lazy[lc[u]] += lazy[u];
    lazy[rc[u]] += lazy[u];
    c[lc[u]] += lazy[u];
    c[rc[u]] += lazy[u];
    lazy[u] = 0;
  }
}
void chg(ll u,ll L,ll R,ll l,ll r,ll cc)
{
  if(L==l && R==r){lazy[u] += cc; c[u] +=cc; return ;}
  push_down(u);
  ll mid = (L+R)>>1;
  if(r<=mid) chg(lc[u],L,mid,l,r,cc);
  else if(l>mid) chg(rc[u],mid+1,R,l,r,cc);
  else
  {
    chg(lc[u],L,mid,l,mid,cc);
    chg(rc[u],mid+1,R,mid+1,r,cc);
  }c[u] = min(c[lc[u]] , c[rc[u]]);
}

ll p[N],a[N],pos[N];

int main()
{
  ll n; cin >> n; rt=tot=0; build(rt,1,n-1);
  for(ll i=1;i<=n;i++) cin >> p[i],pos[p[i]] = i;
  for(ll i=1;i<=n;i++) cin >> a[i];
  for(ll i=1;i<n;i++) chg(rt,1,n-1,i,n-1,a[i]);
  ll ans = c[1];
  for(ll i=1;i<=n;i++)
  {
    if(pos[i] != n) chg(rt,1,n-1,pos[i],n-1,-a[pos[i]]);
    if(pos[i] != 1) chg(rt,1,n-1,1,pos[i]-1,a[pos[i]]);
    ans = min(ans , c[1]);
	}

  return printf("%lld\n",ans),0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39708759/article/details/104120392
今日推荐