传送门
文章目录
- 题意:
- 思路:
题意:
给你三个长度分别为k1,k2,k3k1,k2,k3k1,k2,k3的数组a,b,ca,b,ca,b,c,其中k1+k2+k3=nk1+k2+k3=nk1+k2+k3=n,这三个数组中的元素拼接起来是一个nnn的排列,每次可以将某个数组中的某个元素移动到另一个数组,问最少几次操作使得aaa是1−n1-n1−n的一个前缀,ccc是1−n1-n1−n的一个后缀,bbb包含剩下的数。
n≤2e5n\le2e5n≤2e5
思路:
首先可以想一下只有两个数组的时候我们怎么办,记cnt1icnt1_icnt1i表示第一个数组前iii个数出现的次数,cnt2icnt2_icnt2i表示第二个数组前iii个数出现的次数,那么最终的情况一定是aaa包含[1,i][1,i][1,i],bbb包含[i+1,n][i+1,n][i+1,n],那么答案就是aaa数组[i+1,n][i+1,n][i+1,n]拥有的个数+b+b+b数组[1,i][1,i][1,i]拥有的个数,即cnt1n−cnt1i+cnt2icnt1_n-cnt1_i+cnt2_icnt1n−cnt1i+cnt2i。
现在扩展到了三个数组,那么我们加一个cnt3icnt3_icnt3i,最终的情况就是[1,i],[i+1,j],[j+1,n][1,i],[i+1,j],[j+1,n][1,i],[i+1,j],[j+1,n]分别对应a,b,ca,b,ca,b,c三个数组,那么答案就分为三个部分:aaa中包含[i+1,n][i+1,n][i+1,n]的个数,bbb中包含[1,i],[j+1,n][1,i],[j+1,n][1,i],[j+1,n]的个数,ccc中包含[1,j][1,j][1,j]的个数,答案就是cnt1n−cnt1i+cnt2n−cnt2j+cnt2i+cnt3jcnt1_n-cnt1_i+cnt2_n-cnt2_j+cnt2_i+cnt3_jcnt1n−cnt1i+cnt2n−cnt2j+cnt2i+cnt3j,这个式子直接算的话是n2n^2n2的,显然不可接受,考虑将b,cb,cb,c数组放一起,让后枚举[0,n][0,n][0,n]代表iii,我们只需要找到一个最大的jjj位置即可,由于上面的式子中含jjj的只有两项cnt3j−cnt2jcnt3_j-cnt2_jcnt3j−cnt2j,我们取一个后缀最大值即可。
// Problem: E. The Contest
// Contest: Codeforces - Educational Codeforces Round 76 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1257/problem/E
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int k1,k2,k3,n;
int a[N],b[N],c[N];
int pre1[N],pre2[N],pre3[N];
int cost[N];int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d%d",&k1,&k2,&k3); n=k1+k2+k3;for(int i=1;i<=k1;i++) scanf("%d",&a[i]);for(int i=1;i<=k2;i++) scanf("%d",&b[i]);for(int i=1;i<=k3;i++) scanf("%d",&c[i]);sort(a+1,a+1+k1); sort(b+1,b+1+k2); sort(c+1,c+1+k3);for(int i=1,j=1,k=1,cc=1;i<=n;i++) {pre1[i]=pre1[i-1]; pre2[i]=pre2[i-1];pre3[i]=pre3[i-1];if(a[j]<=i&&j<=k1) pre1[i]++,j++;if(b[k]<=i&&k<=k2) pre2[i]++,k++;if(c[cc]<=i&&cc<=k3) pre3[i]++,cc++;}cost[n+1]=INF;for(int i=n;i>=0;i--) {cost[i]=pre3[i]-pre2[i];cost[i]=min(cost[i],cost[i+1]);}//cost[n+1]=0;int ans=INF;for(int i=0;i<=n;i++) {//if(i==3) cout<<pre3[i]<<endl;ans=min(ans,pre1[n]-pre1[i]+pre2[n]+pre2[i]+cost[i]);}cout<<ans<<endl;return 0;
}
/**/