• CF1257E The Contest


    做一遍前缀和,令 (b_{x,y}) 表示序列 (x) 包含 (1sim y) 的数字有几个。考虑枚举第一个序列保留哪个前缀 (1sim i),对于第三个序列,如果保留了后缀 (jsim n(i<j))

    考虑哪些数需要被移掉,这样恰好能不重不漏。那么答案就是:

    [b_{1,n}-b_{1,i}+b_{2,n}-(b_{2,j-1}-b_{2,i})+b_{3,j-1} ]

    可以发现只要维护 (-b_{2,j-1}+b_{3,j-1}) 的后缀 (min) 就好了,剩下的都是定值。时间复杂度 (O(n)),头尾稍微注意一下。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 200005
    #define Min(x,y)((x)<(y)?x:y)
    #define For(i,x,y)for(i=x;i<=(y);i++)
    #define Down(i,x,y)for(i=x;i>=(y);i--)
    int a1[N],a2[N],a3[N],suf[N];
    int read()
    {
    	int A;
    	bool K;
    	char C;
    	C=A=K=0;
    	while(C<'0'||C>'9')K|=C=='-',C=getchar();
    	while(C>'/'&&C<':')A=(A<<3)+(A<<1)+(C^48),C=getchar();
    	return(K?-A:A);
    }
    int main()
    {
    	int k1,k2,k3,n,i,ans=INT_MAX;
    	k1=read(),k2=read(),k3=read();
    	n=k1+k2+k3;
    	For(i,1,k1)a1[read()]=1;
    	For(i,1,k2)a2[read()]=1;
    	For(i,1,k3)a3[read()]=1;
    	For(i,2,n)
    	{
    		a1[i]+=a1[i-1];
    		a2[i]+=a2[i-1];
    		a3[i]+=a3[i-1];
    	}
    	suf[n]=-a2[n]+a3[n];
    	Down(i,n-1,0)suf[i]=Min(suf[i+1],-a2[i]+a3[i]);
    	For(i,0,n)ans=Min(ans,suf[i]+a1[n]-a1[i]+a2[n]+a2[i]);
    	cout<<ans;
    	return 0;
    }
    
  • 相关阅读:
    7.Linux学习
    5.@AliasFor注解
    5.Maven学习
    3.postman
    4.git总结
    8.Docker学习
    6.idea教程
    2.jwt
    4.open feign
    1.MarkDown常规使用语法
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14513306.html
Copyright © 2020-2023  润新知