CF 967D. Resource Distribution 暴力,二分

题意:n个服务器 第i个服务器最多能负载a[i]单元.现在有两个任务其值为s1,s2
若有一个任务值为S,分给k个服务器 则这k个服务器其a[i]值>=(S+k-1)/k  
每台服务器最多运行一个任务.问任务s1,s2是否能通过这n个服务器运行起来.
n<=3e5.1<=a[i],s1,s2<=1e9  有解输出方案,两个任务各自要用的服务器,否则输出-1.



枚举任务1要用到x台服务器,那么这x台中最小的为val=(s1+x-1)/x 
在a二分找到第一个>=val的下标i,此时显然取[i,i+x-1]是最优的.

现在开始处理s2.
预处理出f[i]表示以i为最小值时,完成s2以后,最多剩下多少个.

那么在枚举完x以后,求出[1,i-1]中是否有f[i]>=x (预处理前缀i中f的最大值),

或者后缀[i+x,n]中是否存在j满足:以j为最小值能满足s2.

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,s1,s2,b[N],f[N];
int pre[N][2],suf[N];
struct node{
	int x,id;
}a[N];
vector<int> v,v1,v2;
bool cmp(node a,node b)
{
	if(a.x==b.x)
		return a.id<b.id;
	return a.x<b.x;
}	
void print(int id,int x,int p)
{
	cout<<"Yes"<<'\n';
	for(int i=id;i<=id+x-1;i++)
		v1.push_back(a[i].id);
	for(int i=p,cnt=1;cnt<=(s2+b[p]-1)/b[p];i++)
	{
		if(i>=id&&i<=id+x-1)
			continue;
		v2.push_back(a[i].id);
		cnt++;
	}
	cout<<v1.size()<<' '<<v2.size()<<'\n';
	for(int i=0;i<v1.size();i++)
		cout<<v1[i]<<' ';
	cout<<'\n';
	for(int i=0;i<v2.size();i++)
		cout<<v2[i]<<' ';
	cout<<'\n'; 		
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>s1>>s2;
	for(int i=1;i<=n;i++)
		cin>>a[i].x,a[i].id=i;	
	sort(a+1,a+1+n,cmp);
	
	for(int i=1;i<=n;i++)
	{
		b[i]=a[i].x;
		int k=(s2+a[i].x-1)/a[i].x;
		if(k<=n-i+1)
			f[i]=n-i+1-k;
		else
			f[i]=-1;
		pre[i][0]=pre[i-1][0];
		pre[i][1]=pre[i-1][1];
		if(f[i]>pre[i-1][0])
			pre[i][0]=f[i],pre[i][1]=i;
	}
	for(int i=n;i>=1;i--)
	{
		if(f[i]!=-1)
		{
			suf[i]=max(suf[i+1],i);
			continue;
		}
		suf[i]=suf[i+1];
	}
	for(int x=1;x<n;x++)
	{
		int val=(s1+x-1)/x;
		int idx=lower_bound(b+1,b+1+n,val)-(b+1)+1;
		if(idx+x-1>n)
			continue;
		int id=idx+x;
		if(suf[id]!=0)
		{
			print(idx,x,suf[id]);
			return 0;
		}
		if(pre[idx-1][0]>=x)
		{
			print(idx,x,pre[idx-1][1]);
			return 0;
		}
	}
	cout<<"No"<<'\n';
	return 0;
}


官方解:

设k1,k2分别为两个任务所用服务器个数. s1<s2

p1=s1/k1,p2=s2/k2  任务1从第一个>=p1的机器开始选k1个.

此时任务2从后缀开始往前取k2个 要满足不能与k1选的重叠 并且这k2个的最小值>=p2.

即任务2的最小值越大越好 也就是无论k1是多少,k2越小越好.

那么直接找到最小的k2,然后在枚举的k1即可. 

tourist代码:

/**
 *    author:  tourist
 *    created: 29.04.2018 16:25:11       
**/
#include <bits/stdc++.h>

using namespace std;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  vector<int> x(2);
  cin >> n >> x[0] >> x[1];
  vector< pair<int,int> > c(n);
  for (int i = 0; i < n; i++) {
    cin >> c[i].first;
    c[i].second = i;
  }
  sort(c.rbegin(), c.rend());
  for (int rot = 0; rot < 2; rot++) {
    int use = -1;
    for (int i = 0; i < n; i++) {
      if (x[0] <= (long long) c[i].first * (i + 1)) {
        use = i + 1;
        break;
      }
    }
    if (use != -1) {
      int use2 = -1;
      for (int i = use; i < n; i++) {
        if (x[1] <= (long long) c[i].first * (i - use + 1)) {
          use2 = i - use + 1;
          break;
        }
      }
      if (use2 != -1) {
        cout << "Yes" << '\n';
        vector< vector<int> > res(2);
        for (int i = 0; i < use; i++) {
          res[rot].push_back(c[i].second);
        }
        for (int i = 0; i < use2; i++) {
          res[rot ^ 1].push_back(c[use + i].second);
        }
        cout << (int) res[0].size() << " " << (int) res[1].size() << '\n';
        for (int q = 0; q < 2; q++) {
          for (int i = 0; i < (int) res[q].size(); i++) {
            if (i > 0) {
              cout << ' ';
            }
            cout << res[q][i] + 1;
          }
          cout << '\n';
        }
        return 0;
      }
    }
    swap(x[0], x[1]);
  }
  cout << "No" << '\n';
  return 0;
}






猜你喜欢

转载自blog.csdn.net/noone0/article/details/80152799