ICPC 2019-2020 North-Western Russia Regional Contest
A
(
√
)
(√)
(√)
B
(
√
)
(√)
(√)
C
D
E
(
√
)
(√)
(√)
F
G
H
I
(
√
)
(√)
(√)
J
(
√
)
(√)
(√)
K
L
M
(
√
)
(√)
(√)
A.Accurate Movement
Meaning:
Initially, there are two wood blocks a and b (a is shorter than b), which are located at the leftmost end. Now move the wood blocks a and b. on the premise that block a cannot exceed block b, ask how many times you can move both a and b to the rightmost end.
Solution:
For board a, the maximum length of each movement (b-a) is, and the number of movements of board a is
(
n
−
b
−
1
)
/
(
b
−
a
)
+
1
(n-b-1)/(b-a)+1
(n−b−1)/(b−a)+1. B board is more than a board. Move the first step and follow a. The total number of times is
(
n
−
b
−
1
)
/
(
b
−
a
)
∗
2
+
3
(n-b-1)/(b-a)*2+3
(n − b − 1)/(b − a) * 2 + 3 times.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 100100 #define mod 1000000009 #define eps 1e-10 template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int a,b,n,ans; cin>>a>>b>>n; ans=(n-b-1)/(b-a)*2+3; cout<<ans; return 0; }
B.Bad Treap
Topic meaning: give the definition of Cartesian tree. Now it is required to give n point pairs (x, sin (x)) to make the height of Cartesian tree as large as possible.
Solution: we only need to find one cycle to minimize the change of sin. Then the function constructed in this period increases the height the slowest and the height the highest.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 200100 #define mod 1000000009 #define eps 1e-10 const int inf = 0x3f3f3f3f; template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,t; double minn=2; int k=0; for(int i=1;i<=50000;i++){ if(sin(i)>0&&sin(i)<minn){ minn=sin(i); k=i; } } cin>>n; for(ll i=1;i<=n;i++){ ll p=-n/2+i; cout<<(ll)p*k<<endl; } return 0; }
E.Equidistant
Give you a graph. Can you find a point so that the distance from this point to all given points is the same.
Solution:
We only need to maintain the maximum distance and the minimum distance. If the maximum distance and the minimum distance are equal, the distance to all points is equal. First take 1 as the root node dfs, then change the root and judge one by one.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 200100 #define mod 1000000009 #define eps 1e-10 const int inf = 0x3f3f3f3f; template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } vector<int>g[maxn]; vector< pair<int,int> >old[maxn]; int s[maxn],maxx[maxn],minn[maxn]; int ans=0; void dfs(int u,int fa){ if(s[u]){ maxx[u]=0;minn[u]=0; } else { maxx[u]=-inf;minn[u]=inf; } for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(v!=fa){ dfs(v,u); maxx[u]=max(maxx[u],maxx[v]+1); minn[u]=min(minn[u],minn[v]+1); } } } void dfs2(int u,int fa){ if(ans)return; if(s[u]){ maxx[u]=0;minn[u]=0; } else{ maxx[u]=-inf;minn[u]=inf; } old[u].push_back(make_pair(maxx[u],minn[u])); for(int i=0;i<g[u].size();i++){ int v=g[u][i]; maxx[u]=max(maxx[u],maxx[v]+1); minn[u]=min(minn[u],minn[v]+1); old[u].push_back(make_pair(maxx[u],minn[u])); } if(maxx[u]==minn[u]){ ans=u; return; } int fmax=-inf,fmin=inf; for(int i=g[u].size()-1;i>=0;i--){ int v=g[u][i]; maxx[u]=max(old[u][i].first,fmax); minn[u]=min(old[u][i].second,fmin); fmax=max(fmax,maxx[v]+1); fmin=min(fmin,minn[v]+1); if(v!=fa)dfs2(v,u); } } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,m,u,v,x; cin>>n>>m; memset(s,0,sizeof s); for(int i=1;i<n;i++){ cin>>u>>v; g[u].push_back(v); g[v].push_back(u); } for(int i=1;i<=m;i++){ cin>>x; s[x]=1; } dfs(1,0); dfs2(1,0); if(ans)cout<<"YES\n"<<ans; else cout<<"NO"; return 0; }
I.Ideal Pyramid
Meaning:
To find a point in a two-dimensional space, build a pyramid with the minimum height and an angle of 45 degrees. All given obelisks are required.
First, because the angle is 45 degrees. So we can turn every Obelisk into a pyramid. The left boundary of the pyramid is
x
−
h
x-h
x − h, with boundary
x
+
h
x+h
x+h, height
h
h
h. Because there is a 45 degree angle, the height can be calculated by dividing the sum of the left and right boundaries by two. Then we just need to maintain the values of the lower left and right boundaries. Calculate the minimum height of the x-axis at the leftmost section and the rightmost end of the x-axis, and calculate it again on the y-axis. The height shall meet two conditions at the same time, whichever is greater.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 200100 #define mod 1000000009 #define eps 1e-10 const int inf = 0x3f3f3f3f; template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,x,y,h,xl,xr,yl,yr; cin>>n; xl=inf;xr=-inf;yl=inf;yr=-inf; for(int i=1;i<=n;i++){ cin>>x>>y>>h; xl=min(xl,x-h);xr=max(xr,x+h); yl=min(yl,y-h);yr=max(yr,y+h); } int ansh=0; ansh=max(ansh,(xr-xl+1)/2); ansh=max(ansh,(yr-yl+1)/2); cout<<(xr+xl)/2<<" "<<(yr+yl)/2<<" "<<ansh; return 0; }
J.Just the Last Digit
Meaning:
A person will only go to places with large numbers. Now he's recording everything from
i
i
i to
j
j
The single digit of the number of schemes of j. I want you to find all the unidirectional edges
i
i
i to
j
j
Whether j exists.
Solution:
Because he only goes in the big direction, so
a
n
s
[
i
]
[
j
]
=
∑
k
=
i
+
1
j
−
1
a
n
s
[
i
]
[
k
]
∗
a
n
s
[
k
]
[
j
]
ans[i][j]=\sum_{k=i+1}^{j-1}ans[i][k]*ans[k][j]
ans[i][j] = ∑ k=i+1j − 1 ans[i][k] * ans[k][j], if
i
i
i to
j
j
If j has a one-way side,
a
n
s
[
i
]
[
j
]
=
a
n
s
[
i
]
[
j
]
+
1
ans[i][j]=ans[i][j]+1
ans[i][j]=ans[i][j]+1. We can judge whether there is an edge by whether there is a difference of one.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 200100 #define mod 1000000009 #define eps 1e-10 const int inf = 0x3f3f3f3f; template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } char s[555][555]; int a[555][555]; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>s[i][j]; a[i][j]=s[i][j]-'0'; } } for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ ll ans=0; for(int k=i+1;k<=j-1;k++){ ans+=a[i][k]*a[k][j]; } ans%=10; if(ans!=a[i][j])a[i][j]=1; else a[i][j]=0; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cout<<a[i][j]; } cout<<endl; } return 0; }
M.Managing Difficulties
Meaning:
How many can you find
s
[
j
]
−
a
[
i
]
=
a
[
k
]
−
a
[
j
]
s[j]-a[i]=a[k]-a[j]
s[j]−a[i]=a[k]−a[j],
i
<
j
<
k
i<j<k
i<j<k.
Solution:
How many do we look from front to back
a
[
i
]
a[i]
a[i],
a
[
i
]
=
2
∗
a
[
j
]
−
a
[
k
]
a[i]=2*a[j]-a[k]
a[i]=2 * a[j] − a[k], just add up the answers.
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> #include <utility> #include <cassert> using namespace std; #define ll long long #define maxn 100100 #define mod 1000000009 #define eps 1e-10 template <typename T> inline void read(T& X) { X = 0; int w = 0; char ch = 0; while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar(); if (w) X = -X; } ll a[22222]; map<ll,ll>mp; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t,n; cin>>t; while(t--){ mp.clear(); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } ll count = 0; mp[a[1]]++; for(int i=2;i<n;i++){ for(int j=i+1;j<=n;j++){ ll p=2*a[i]-a[j]; if(!mp.count(p)||p<0)continue; count+=mp[p]; } mp[a[i]]++; } printf("%lld\n",count); } return 0; }