[Codeforces 1295E]Permutation Separation(线段树+贪心)
[Codeforces 1295E]Permutation Separation(线段树+贪心)
题面
给出一个排列\(p_1,p_2,...p_n\).初始时你需要选择一个位置把排列分成左右两个。然后在两个序列间移动元素使得左边序列的所有元素都比右边的所有元素小。给出每个元素\(p_i\)从一个序列移动到另一个序列的代价\(a_i\).
分析
显然最后得到的序列是小的数在一边,大的数在另一边。设从值为\(i\)的元素处分开之后移动代价为\(ans_i\). 一开始假设所有数都移到右边序列,那么\(ans_i\)就是值\(\leq i\)的元素的代价之和。然后从1~n枚举分割点\(i\)。对于\(p_i\),它放到左边之后\(ans[p_i+1,n]\)都需要去掉代价(因为\(p_i\)一开始就在左边,不需要移动)\(a_i\).而\(ans[0,p_i-1]\)需要增加代价\(a_i\).当前答案就是所有ans的最小值.
用线段树维护ans数组,时间复杂度为\(O(n\log n)\)
代码
#include<iostream> #include<cstdio> #include<cstring> #define INF 0x3f3f3f3f3f3f3f3f #define maxn 200000 using namespace std; typedef long long ll; struct segment_tree{ struct node{ int l; int r; ll val; ll mark; }tree[maxn*4+5]; void push_up(int pos){ tree[pos].val=min(tree[pos<<1].val,tree[pos<<1|1].val); } void build(int l,int r,int pos){ tree[pos].l=l; tree[pos].r=r; if(l==r) return; int mid=(l+r)>>1; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); } void add_tag(int pos,ll mark){ tree[pos].val+=mark; tree[pos].mark+=mark; } void push_down(int pos){ if(tree[pos].mark){ add_tag(pos<<1,tree[pos].mark); add_tag(pos<<1|1,tree[pos].mark); tree[pos].mark=0; } } void update(int L,int R,int val,int pos){ if(L<=tree[pos].l&&R>=tree[pos].r){ add_tag(pos,val); return; } push_down(pos); int mid=(tree[pos].l+tree[pos].r)>>1; if(L<=mid) update(L,R,val,pos<<1); if(R>mid) update(L,R,val,pos<<1|1); push_up(pos); } inline ll get_min(){ return tree[1].val; } }T; int n; int p[maxn+5],a[maxn+5]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&p[i]); } for(int i=1;i<=n;i++) scanf("%d",&a[i]); T.build(0,n,1);//线段树的区间[i,i]表示开始在值i位置分开的答案ans[i] for(int i=1;i<=n;i++){//一开始假设所有数都移到右边,那么ans[i]就是p的前缀和sum[i] T.update(p[i],n,a[i],1); } ll ans=INF; for(int i=1;i<n;i++){//贪心,把小的数放到左边,枚举哪些数要放 T.update(p[i],n,-a[i],1);//去掉p[i]从右到左的代价 T.update(0,p[i]-1,a[i],1); ans=min(ans,T.get_min()); } printf("%I64d\n",ans); }
版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步