zoukankan      html  css  js  c++  java
  • Codeforces Global Round 2 D 差分 + 前缀和 + 二分

    https://codeforces.com/contest/1119/problem/D

    题意

    有n个数组,每个数组大小为(10^{18}+1)且为等差数列,给出n个数组的(s[i]),q次询问,每次询问一个区间[l,r],问所有数组的[l,r]区间一共有多少不同的数

    题解

    • 结果只与选择的区间长度len有关,还有和两个数组s[i]的差cha有关
      • 若len<=cha,则没有重复,即(2*len)
      • 若len>cha,则前面一个数组可以取满len个,后面的数组只能cha个,即(cha+len)
    • 根据以上规律,将a数组进行排序后差分,对差分进行排序,然后做前缀和,每次二分查找出最大的p满足b[p]<=x
    • 这里二分查找需要特判l>r的情况

    代码

    #include<bits/stdc++.h>
    #define ll long long 
    #define MAXN 100005
    using namespace std;
    ll a[MAXN],b[MAXN],s[MAXN],q,n,x,p,ans,l,r,sz;
    
    int fd(ll x){
    	int l=1,r=sz-1,res=0;
    	while(l<r){
    		int mid=(l+r)/2;
    		if(b[mid]<=x)l=mid+1;
    		else r=mid;
    	}
    	if(l>r||b[l]>x)l--;                         //特判
    	return l;
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    	}
    	sort(a+1,a+n+1);
    	sz=unique(a+1,a+n+1)-(a+1);
    	for(int i=2;i<=sz;i++)b[i-1]=a[i]-a[i-1];
    	sort(b+1,b+sz);
    	for(int i=1;i<sz;i++)s[i]=s[i-1]+b[i];
    	cin>>q;
    	while(q--){
    		scanf("%lld%lld",&l,&r);
    		x=r-l+1;
    		p=fd(x);
    		ans=s[p]+(sz-p)*x;
    		printf("%lld ",ans);
    	}
    }
    
  • 相关阅读:
    axios的使用/
    jQuery好玩的双向控制轮播
    vue的路由跳转方式/两种
    vfor的某些注意事项
    vue使用插件时不能撑满页面?
    swiper中的双向控制器不生效问题
    sass的安装及使用
    .net必懂题
    软件架构初读01
    EJB
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/10808913.html
Copyright © 2011-2022 走看看