zoukankan      html  css  js  c++  java
  • [Codeforces 1199C]MP3(离散化+二分答案)

    [Codeforces 1199C]MP3(离散化+二分答案)

    题面

    给出一个长度为n的序列(a_i)和常数I,定义一次操作[l,r]可以把序列中<l的数全部变成l,>r的数全部变成r。每次操作的代价为改变数的个数。问:要让操作后序列里不同数的个数(k)满足$n lceil log _2 k ceil leq 8I $,操作的最小代价

    分析

    首先把a离散化,这样[l,r]都在(10^5)的级别。枚举l,发现r显然有单调性。操作后不同数的个数随r的增大而减小(考虑极端情况l=r,操作后所有数相同。若(r_1)满足条件,那(r_2<r_1)也一定满足条件。而操作的最小代价随r增大而减小。所以我们只需要对于每个l找到最大的满足条件的r即可。

    考虑判定:我们把a排序,记(cnt(l,r))表示满足(a_i in [l,r])(i)的个数,m为离散化后的最大值。那么操作的代价为(cnt(1,l-1)+cnt(r+1,m)),不同数的个数为(r-l+1)(操作完之后最小值变成l,最大值变成r,由于我们离散化过,[l,r]内的数一定是连续的,所有个数为[r-l+1])

    那么我们只要预处理前缀和(sum(v))表示整个序列值<=v的个数,离散化后可以(O(n))预处理,(cnt(l,r)=sum(r)-sum(l-1))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define INF 0x3f3f3f3f
    #define maxn 800000
    using namespace std;
    int n,m,I;
    int a[maxn+5];
    int b[maxn+5];
    int sum1[maxn+5];
     
    inline int cnt(int l,int r){
    	return sum1[r]-sum1[l-1];
    }
    int check(int lb,int rb){
    	int ans1=cnt(1,lb-1);
    	int ans2=cnt(rb+1,m);
    	int k=rb-lb+1;
    //	int cnt=2+sum1[lb+1]+sum1[rb-1];
    	if(ceil(log2(k))*n<=I*8) return ans1+ans2;
    	else return -1;
    }
    int bin_search(int t){
     
    	int l=t,r=m;
    	int ans=INF;
    	int mid;
    	while(l<=r){
    		mid=(l+r)>>1;
    		int val=check(t,mid);
    		if(val!=-1){
    			ans=val;
    			l=mid+1;
    		}else r=mid-1;
    	}
    	return ans;
    }
     
    int mark[maxn+5];
    int main(){
    //	freopen("input.txt","r",stdin);
    	scanf("%d",&n);
    	scanf("%d",&I);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		b[i]=a[i];
    	}
    	sort(a+1,a+1+n);
    	sort(b+1,b+1+n);
    	m=unique(b+1,b+1+n)-b-1;
    	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+m,a[i])-b;
    	for(int i=1;i<=n;i++){
    		sum1[a[i]]++;
    	}
    	for(int i=1;i<=m;i++) sum1[i]+=sum1[i-1];
    //	printf("%d
    ",m);
    	int ans=INF;
    	for(int l=1;l<=m;l++){
    		int tmp=bin_search(l);
    		ans=min(ans,tmp);
    	}
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    解决Windows 10每次重启默认浏览器都被重置为IE的一个办法
    使用cookie登录百度网盘账号
    【C++ Primer | 14】重载运算
    Visual Studio Code 快捷键的使用
    【C++ Primer | 8】IO库
    Git push常见用法
    Git 基础
    Git连接GitHub仓库详解
    ceph关于rpm包构建的教程
    monitor综合
  • 原文地址:https://www.cnblogs.com/birchtree/p/11273809.html
Copyright © 2011-2022 走看看