zoukankan      html  css  js  c++  java
  • [Atcoder2292] Division into Two

    题目大意

    给定n个不同的整数,求将它们分成两个集合X,Y,并且X集合中任意两个数的差>=A,Y集合中任意两个数的差>=B的方案数。

    样例输入

    5 3 7
    1
    3
    6
    9
    12

    样例输出

    5

    解析

    不妨设(A>B),那么考虑如何动态规划。设(f[i])表示第一个集合最后选择的数是i时的方案数。只用枚举第一个集合前一个选的数是哪一个即可转移。但 这么做是(O(n^2))的。考虑从能够转移的点的性质出发。

    对于能够转移到i的j,必须要满足的条件有

    • (S_i-S_j >= A)
    • 对于([j+1,i-1])中的数,满足任意两个数(x,y)都有(S_y-S_x>=B)

    可以发现满足条件的j是一段连续位置。因此采用前缀和优化即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define int long long
    #define N 100002
    using namespace std;
    const int mod=1000000007;
    int n,a,b,i,m[N],sum[N],f[N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    signed main()
    {
    	n=read();a=read();b=read();
    	if(a>b) swap(a,b);
    	for(i=1;i<=n;i++) m[i]=read();
    	sort(m+1,m+n+1);
    	for(i=3;i<=n;i++){
    		if(m[i]-m[i-2]<a){
    			puts("0");
    			return 0;
    		}
    	}
    	int l=0,r=0,ans=0;
    	sum[0]=f[0]=1;
    	for(i=1;i<=n;i++){
    		while(r<i-1&&m[i]-m[r+1]>=b) r++;
    		if(l<=r) f[i]=(sum[r]-sum[l-1]+mod)%mod;
    		sum[i]=(sum[i-1]+f[i])%mod;
    		if(i>1&&m[i]-m[i-1]<a) l=i-1;
    	}
    	for(i=n;i>=0;i--){
    		ans=(ans+f[i])%mod;
    		if(i<n&&m[i+1]-m[i]<a) break;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    zabbix实现mysql数据库的监控(四)
    Redis高级进阶(一)
    Redis高级进阶(二)
    Redis的管理
    9.动态SQL
    8.Mapper动态代理
    7.属性名与查询字段名不相同
    6.单表的CRUD操作
    5.API详解
    4.主配置文件详解
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11879120.html
Copyright © 2011-2022 走看看