Educational Codeforces Round 131 (Rated for Div. 2)A~D
b看错题草,dwa了9发才过巨草,c为了过快点写的很丑
Problem - A - Codeforces
问题解析
直接算这四个格子的和是多少,为0那就一次也不用,小于等于3只要一次就可以,等于4则是两次
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 1e9 + 7;
void solve()
{
int a, b, c, d;
cin >> a >> b >> c >> d;
if (a + b + c + d == 0)cout << 0 << endl;
else if (a + b + c + d <= 3)cout << 1 << endl;
else cout << 2 << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
Problem - B - Codeforces
问题解析
题目这里说的是让你选一个d,让a[i]*d==a[i+1]的结果尽量多,那就d取尽可能小的,即2,然后排列尽量排成a[i+1]=a[i] *2的样子即可。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 1e9 + 7;
void solve()
{
int n;
cin >> n;
vector<int>v(n + 1);
cout << 2 << endl;
for (int i = 1; i <= n; i ++)
{
for (int j = i; j <= n; j *= 2)
{
if (v[j] == 0)
{
cout << j << " ";
v[j] = 1;
}
}
}
cout << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
Problem - C - Codeforces
问题解析
贪心+二分答案。我们可以二分枚举需要的最少时间,上界最大是所有任务都是不擅长的人去做:2*m,下届是每个人正好都有一个擅长的任务:1。
check:我们可以先记录一下每个人有多少个要做的擅长任务,如果这个任务数大于了时间,说明这个人没法做完所有他擅长的工作,那么这个工作就要给比较空闲的人去做(即擅长任务少的人)。所以我先把所有人擅长的任务数升序排序,这样就可以让擅长任务少的人去做多余的工作。如果所有人的工作时间都无法在增长,但还有任务没做完,那说明我们的时间少了,反之时间充足。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 1e9 + 7;
int f[N], n, m;
set<PII>st;
bool check(int mid)
{
//times[i]表示第i个员工已经工作了times[i]小时
//ans表示第i个员工做了ans[i]个不擅长的工作
vector<int>times(n + 1),ans(n+1);
auto t = st.begin();
for (int i = 0; i < m; i++)
{
//擅长的任务数小于我们二分的时间就让擅长的人做
if (times[f[i]] < mid)times[f[i]]++,ans[f[i]]++;
else
{
//t.second是一个员工的编号,first是他擅长任务的数量
//(*t).first-ans[(*t).second]就得到这个员工还要做多少个擅长的任务
//下面这一串式子表示:这个员工已经工作过的时间+还要做擅长的任务数+完成这个多余任务(2小时)所要的时间是否小于mid
if (times[(*t).second]+(*t).first-ans[(*t).second] + 2 <= mid)
{
//小于就让这个人做
times[(*t).second] += 2;
}
else
{
//做不了我们就去找下一个能做的
while (t!=st.end()&×[(*t).second] + (*t).first - ans[(*t).second] + 2 > mid)t++;
//所有人都做不了这个任务,返回false
if (t == st.end())return false;
//找到能做的就让他做
times[(*t).second] += 2;
}
}
}
return true;
}
void solve()
{
st.clear();
cin >> n >> m;
vector<int>v(n + 1);
for (int i = 0; i < m; i++)
{
cin >> f[i];
//v记录每个人有多少个擅长的任务
v[f[i]]++;
}
for (int i = 1; i <= n; i++)
//通过set的自动排序,把擅长任务数少的人放在前面
st.insert({ v[i],i });
int l = 1, r = m * 2;
while (l < r)
{
int mid = (l + r) / 2;
if (check(mid))r = mid;
else l = mid + 1;
}
cout << l << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
Problem - D - Codeforces
问题解析
先按照b[i]的值,来算得第i个位置能取的数的范围:i / (b[i]+1)+1到i / b[i]。如果b[i]为0,那么只要大于i的数都可以,如果是b[i]==i,那么这个位置就只能是1。
然后我们按照每个位置的取值范围来排序,我们尽量把右区间小的放在前面,然后每次取值的时候,都取一个最小的且还没被拿过的数。
但是直接这么写我t了,想了想原因应该是在区间l~r上找最小的且还没被拿过的数这一步骤出了问题。假设区间是[1,1000],但其实前面999个位置都已经被拿过了,但我们还是从1开始傻傻的找,很蠢。
所以我们可以用一个变量ans优化一下。ans表示所有数中还没被取走的最小的数,这样当左区间小于ans时,我们直接从ans开始找就行。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 1e9 + 7;
int f[N];
vector<vector<int>>st;
bool cmp(vector<int>a, vector<int>b)
{
if(a[2]!=b[2])
return a[2] < b[2];
return a[1] < b[1];
}
void solve()
{
st.clear();
int n;
cin >> n;
vector<int>v(n + 1), res(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> f[i];
int l, r;
if (f[i] == i)
{
res[i] = 1;
v[1] = 1;
}
if (f[i] == 0)
{
l = i+1, r = n;
}
else
{
l = i / (f[i] + 1) + 1, r = i / f[i];
}
vector<int>ans{ i,l,r };
st.push_back(ans);
}
sort(st.begin(), st.end(), cmp);
int pos = 1;
for (auto i : st)
{
while (v[pos])pos++;
int x = i[0], l = i[1], r = i[2];
for (int j = max(pos,l); j <= r; j++)
{
if (v[j] == 0)
{
v[j] = 1;
res[x] = j;
break;
}
}
}
for (int i = 1; i <= n; i++)
{
cout << res[i] << " ";
}
cout << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}