Educational Codeforces Round 146 (Rated for Div. 2)

Problem - D - Codeforces

思路:

  1. 首先,答案一定至多是n,把所以值改为f的最小公倍数即可
  2. 如果我们打算减少,那么意味着至少有一把武器是不用修改,数据范围允许复杂度为O(n^2),因此我们可以枚举每个武器以他的p为区间点,枚举他所在的范围区间从[ max(p,k+1)-k,max(p,k+1)]到[p,p+k],然后判断是否不在区间内的武器都可以修改到这里,不可以就退出
  3. 按上面说复杂度其实是O(n^2*k),直接上肯定tle
    1. 我们又注意到如果f<=k+1,我们一定可以修改他到合法区间[L,L+K]的,那么这些数一开始就可以提出判断是否能够修改到区间的讨论里面,因他们一定可以
    2. 对于不确定的f,假设当前上限为R,那么需要满足\left \lfloor \frac{R}{f} \right \rfloor *f>=R-k\Leftrightarrow k>=R-\left \lfloor \frac{R}{f} \right \rfloor\Leftrightarrow k>=(R%f)k是固定的,我们可以给f排序(大到小),那么越大的f可以使右边尽可能保持大(因为R>=k+1),(比如如果有R/f==0,那么一定满足k
    3. 再把需要讨论的f删去重复的,最后时间会极大缩减
#include 
using namespace std;
#define ll               long long
#define endl             "\n"
#define int              long long
#define endll            endl< pii;
typedef pair pll;
//---------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------//
//double 型memset最大127,最小128
const int INF = 0x3f3f3f3f;         //int型的INF
const ll llINF = 0x3f3f3f3f3f3f3f3f;//ll型的llINF
const int N = 2e5 + 10;

int cal(vector&a,int l,int r) //计算不要修改的区间包含的数
{
	return upper_bound(a.begin(),a.end(),r)-lower_bound(a.begin(),a.end(),l);
}

void mysolve()
{
	int n,x,k;
	cin>>n>>k;
	vectorf(n),a(n);
	for(int i=0; i>f[i];
	for(int i=0; i>x,a[i]=f[i]*x;
	sort(f.begin(),f.end(),greater());//注意,使用unique前需要先排序
	while(f.size()&&f.back()<=k+1)f.pop_back();//对于一定可以成功修改的,直接提出讨论
	f.resize(unique(f.begin(),f.end())-f.begin());//删除重复的数

	sort(a.begin(),a.end());//我们从小到大枚举区间范围
	int ans=n,r=k+1;//r至少从k+1开始,小于他则没有必要讨论,我们是利用a的值跳跃遍历[R-k,R]的区间
	for(auto u:a)
		{
			for(r=max(r,u); r<=u+k; ++r)
				{
					bool flag=1;
					for(auto p:f)//f从大到小遍历
						{
							if(k> t;
	while (t--)
		{
			mysolve();
		}
	system("pause");
	return 0;
}

你可能感兴趣的:(CF杂栏,c++,算法,图论)