Codeforces Round 615 div3 Solution
Problem A. Collecting Coins
Solution
Observe that the easiest solution would be increase every one's number of coins to \(\max(A,B,C)\)
Then all we have to do is to distribute the coins left evenly to three of them
which is typically just checking if the number of coins left is divisible to 3
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
int t;
sf("%d",&t);
while(t--)
{
int a,b,c,n;
sf("%d%d%d%d",&a,&b,&c,&n);
int mx = max(a,max(b,c));
int d = (mx-a)+(mx-b)+(mx-c);
if(d > n) pf("NO\n");
else if((n-d)%3) pf("NO\n");
else pf("YES\n");
}
return 0;
}
Problem B. Collecting Packages
Solution
Observe that the only situation where there is a solution is you can rearrange packages in a way that the x-cor is increasing and y-cor is increasing simultaneously
Printing the path would be an easy job to do
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
const int maxn = 1005;
int n;
pii a[maxn];
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
int t;
sf("%d",&t);
while(t--)
{
sf("%d",&n);
fo(i,1,n) sf("%d%d",&a[i].fi,&a[i].se);
sort(a+1,a+n+1);
int cx = 0, cy = 0;
string ans = "";
fo(i,1,n)
{
while(cx < a[i].fi)
{
cx ++;
ans += "R";
}
while(cy < a[i].se)
{
cy ++;
ans += "U";
}
if(cx != a[i].fi || cy != a[i].se)
{
pf("NO\n");
goto gg;
}
}
pf("YES\n");
cout << ans << endl;
gg:;
}
return 0;
}
Problem C. Product of three numbers
Solution
It's easy to think about factorising N, except we have to group all the factors in a way that there are only 3 of them
and 3 of them have to be distinct
we can simply just construct a solution of \(a,b,c\) where \(a<b<c\) by merging some of the factors
then we can just multiply \(c\) by the product of the factors left.
there are some special cases need to be handled, but it should not be hard.
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
int a[4];
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
int t;
sf("%d",&t);
while(t--)
{
int n; sf("%d",&n);
int now = 1;
fo(i,1,3) a[i] = 1;
for(int i = 2; 1ll * i * i <= n; ++ i)
while(n%i==0)
{
n /= i;
a[now] *= i;
// D("%d %d %d\n",now,n,a[now]);
if(now == 1 || a[now] > a[now-1])
++ now;
if(now == 4) goto gg;
}
gg:;
if(now == 3 && n*a[3] != 1 && n*a[3] != a[1] && n*a[3] != a[2])
printf("YES\n%d %d %d\n",a[1],a[2],n*a[3]);
else if(now != 4) printf("NO\n");
else printf("YES\n%d %d %d\n",a[1],a[2],a[3]*n);
}
return 0;
}
Problem D. MEX maximizing
Solution
Notice that we can transform each \(y_{i}\) to \(y_{i}\mod X+X\times k\)
then instead of treating the actual array, we are working with a new array consists of modulo
Observing them in a way of building blocks, we can make following observations :
1) we don't have to discard our operations, which is saying the answer will be monotonically increasing
2) the answer must be \(base + extra\)
\(base\) is basically \(X\times f\) where \(f\) is the minimum of that new array
\(extra\) is the smallest position where it possesses the value of the minimum.
I used a rangetree to support the operations described above, time complexity of this approach would be \(O(n\log n)\)
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
const int maxn = 400050;
const int maxm = 400000;
int q, x, p;
struct tre{int l, r, mn;}t[maxn<<2];
void build(int l, int r, int k = 1)
{
if(l == r) return;
t[k].l = l; t[k].r = r;
int mid = l + r >> 1;
build(l, mid, k<<1);
build(mid+1, r, k<<1|1);
}
void add(int p, int k = 1)
{
if(t[k].l == t[k].r) {t[k].mn ++; return;}
int mid = (t[k].l + t[k].r) >> 1;
if(p <= mid) add(p, k<<1);
else add(p, k<<1|1);
t[k].mn = min(t[k<<1].mn, t[k<<1|1].mn);
}
int work(int l, int r, int k = 1)
{
if(l == r) return l;
int mid = l + r >> 1;
if(t[k<<1].mn == t[1].mn) return work(l, mid, k<<1);
else return work(mid+1, r, k<<1|1);
}
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
sf("%d%d",&q,&x);
build(0, x-1);
while(q--)
{
int y; sf("%d",&y);
y%=x; add(y);
// D("%d %d\n",t[1].mn,work(0,x-1));
pf("%d\n",t[1].mn*x+work(0,x-1));
}
return 0;
}
Problem E. Obtain a permutation
Solution
From the conditions we are given, it's not hard to come up with those observations:
1) Columns are independent to each other
2) There is no point for modifying a grid more than once
with the first observation, we have an idea of sweeping from left to right, solve by columns
now for the first column, we have N scenarios of cyclically shifting it, to do this, we append the whole array to the back of itself
After that, our question is narrowed down to, if we are given a starting point, how many ceils do not need to be changed?
this is easy after some maths work
the condition would be \(a[k]=i+(k-j)\times m\), where \(a[k]\) is the \(k\)th number in the new array.
\(i\) is the supposed starting number of our column
and \(j\) is the assumed starting point.
by playing with algebra, we can rewrite the conditions in this way : \(a[k]-k\times m=i-j\times m\)
we can simply use two-pointers technique and multiset data structure to solve this problem
time complexity would be \(O(nm\log n)\)
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define VI vector<int>
#define pii pair<int,int>
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
const int maxn = 200050;
int n, m, b[maxn*2], ans;
VI a[maxn];
multiset<int> Set;
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
sf("%d%d",&n,&m);
fo(i,1,n) {a[i].pb(-1); fo(j,1,m) {int x; sf("%d",&x); a[i].pb(x);}}
fo(i,1,m)
{
fo(j,1,n) b[j] = b[j+n] = a[j][i];
// fo(j,1,n) b[j+n] = b[j];
fo(j,1,n*2) b[j] = b[j] - j*m;
Set.clear();
fo(j,1,n) Set.insert(b[j]);
int mn = (1<<30);
fo(j,1,n)
{
int v = Set.count(i-j*m);
mn = min(mn, j - 1 + n - v);
Set.erase(Set.find(b[j]));
Set.insert(b[j+n]);
}
// D("%d\n",mn);
ans += mn;
}
printf("%d\n",ans);
return 0;
}
Problem F. Three paths on a tree
Solution
This is an interesting question, i firstly made such an observation:
if in the subtree of \(X\), there are less than 3 nodes are colored, then the edge \((fa[x],x)\) must be taken into account
I think this observation will lead to an interesting DP solution but i have no idea right now.
After playing with a few cases, I observed that the diameter of the tree must be included in the answer.
This is quite obvious once you are cleared that the path between \(a,b,c\) is basically just
the path \(P\) between two of them (1)
+ the path between the one left and one node on path \(P\) (2)
Question is, can we arbitrarily pick a diameter? the answer is YES
this is because if there are two distinct diameters, we can simply just join them to obtain a longer diameter
which is contradicted to diameter's definition
Finding a diameter should be easy, then squeeze the diameter and rebuild the tree and find the deepest node
#include <bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define mp make_pair
#define fi first
#define se second
#define VI vector<int>
#define pii pair<int,int>
#define pb push_back
#define fp freopen
#ifdef MPS
#define D(x...) printf(x)
#else
#define D(x...)
#endif
typedef long long ll;
typedef double db;
const int maxn = 200050;
int n, cnt, mx, ans, dep[maxn], squeeze[maxn];
vector<pii> g[maxn];
struct edge{int u, v;}e[maxn];
void dfs(int x)
{
if(dep[x] > dep[mx]) mx = x;
for(auto p : g[x])
if(!dep[p.fi])
{
dep[p.fi] = dep[x] + 1;
dfs(p.fi);
}
}
bool color(int x)
{
if(x == mx) return true;
for(auto p : g[x])
if(dep[p.fi] == dep[x] + 1 && color(p.fi))
{
++ ans;
squeeze[p.fi] = true;
return true;
}
return false;
}
int main()
{
#ifdef MPS
fp("1.in","r",stdin);
fp("1.out","w",stdout);
#endif
sf("%d",&n);
fo(i,2,n)
{
sf("%d%d",&e[i].u,&e[i].v);
g[e[i].u].pb(mp(e[i].v, ++ cnt));
g[e[i].v].pb(mp(e[i].u, cnt));
}
dep[1] = 1;
dfs(1);
int a = mx;
memset(dep,0,sizeof(dep));
mx = 0;
dep[a] = 1;
dfs(a);
int b = mx;
squeeze[a] = true;
color(a);
fo(i,1,n) g[i].clear();
fo(i,2,n)
if(!squeeze[e[i].u] && !squeeze[e[i].v])
{
g[e[i].u].pb(mp(e[i].v, 1));
g[e[i].v].pb(mp(e[i].u, 1));
D("edge %d %d\n",e[i].u,e[i].v);
}
else if(squeeze[e[i].u] && squeeze[e[i].v]) continue;
else
{
int u = e[i].u, v = e[i].v;
if(squeeze[e[i].u]) u = n+1;
if(squeeze[e[i].v]) v = n+1;
g[u].pb(mp(v,0));
g[v].pb(mp(u,0));
D("edge %d %d\n",u,v);
}
mx = 0;
memset(dep,0,sizeof(dep));
dep[n+1] = 1;
dfs(n+1);
if(mx == n+1)
{
fo(i,1,n) if(squeeze[i] && i != a && i != b)
{
mx = i;
dep[mx] = 1;
break;
}
}
printf("%d\n%d %d %d",ans+dep[mx]-1,a,b,mx);
return 0;
}

浙公网安备 33010602011771号