CodeForces ——C. Cram Time
题目链接
解题报告:
贪心的思想,从1开始找一个范围**[1,n]**,读完这个范围内的所有讲义一定就是最多的讲义数啦~~
要读完这个范围所有的讲义需要的时间 time = n*(n+1)/2
emmmmmm二分找一个最佳的n 满足 n*(n+1)/2 <= sum(a+b) 就行好啦,嘻嘻。
可以对n预先优化(当然不优化直接带 n = sum也可以AC ),因为n不可能== sum(a+b) , 而且很容易找出规律n一定接近 sqrt(2 * sum) 也就是 n <= sqrt(2 * sum) 。找到n后,因为1~n内的讲义都能看完,那就从后面贪心选,这样一定能保证最差的情况(刚好用完两天的时间和)
即: n*(n+1)/2 = sum(a+b)时刚好能选完!!!
/*
* @Author: Achan
* @Date: 2018-10-22 20:54:02
* @Last Modified by: Achan
* @Last Modified time: 2018-10-23 19:51:44
*/
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define X first
#define Y second
#define eps 1e-2
#define gcd __gcd
#define pb push_back
#define PI acos(-1.0)
#define lowbit(x) (x)&(-x)
#define bug printf("!!!!!\n");
#define mem(x,y) memset(x,y,sizeof(x))
#define rep(i,j,k) for(int i=j;i<(int)k;i++)
#define per(i,j,k) for(int i=j;i<=(int)k;i++)
#define io std::ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);
typedef long long ll;
typedef long double LD;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const int inf = 1<<30;
const ll INF = 1e18 ;
const int mod = 1e9+7;
const int maxn = 2e5+2;
vector <int > va;
vector <int > vb;
int A[maxn];
int B[maxn];
//#define LOCAL
int main(void)
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
io
ll a,b;
cin>>a>>b;
ll sum = a+b;
ll n = sqrt(2*sum); // n的大概上界
ll l = 1;
ll r = n;
while(l<=r) //二分寻找一个最佳的n
{
ll m = (l+r)>>1;
if( (m*(m+1)>>1) <= sum ) //满足a+b 能读到前m本
{
n = m; //维护最佳的n
l = m+1;
}
else r = m-1 ;
}
ll t = n;
int p,q;
p = q = 0;
while(t>0) //n个数一定都能成功输出,倒着贪心
{
if(a>=t)
{
A[p++] = t;
//va.pb(t);
a-=t;
t--;
}
else
{
B[q++] = t;
//vb.pb(t);
b-=t;
t--;
}
}
cout<<p<<endl;
rep(i,0,p) cout<<A[i]<<" ";
cout<<endl;
cout<<q<<endl;
rep(i,0,q) cout<<B[i]<<" ";
cout<<endl;
// cout<<va.size()<<endl;
// rep(i,0,va.size()) cout<<va[i]<<" ";
// cout<<endl;
// cout<<vb.size()<<endl;
// rep(i,0,vb.size()) cout<<vb[i]<<" ";
// cout<<endl;
}