目录
2021年度训练联盟热身训练赛第八场
A-Fire on Field
题意
构造数组,使得对于所有的 k ( i − 2 k > 0 ) k \ (i - 2k > 0) k (i−2k>0) 都有 a [ i ] − a [ i − k ] ! = a [ i − k ] − a [ i − 2 k ] a[i] - a[i - k] != a[i - k] - a[i - 2k] a[i]−a[i−k]!=a[i−k]−a[i−2k] 。输出第 n n n 项。
思路
开始以为是有什么规律可循的构造,想了半天想不出,一看数据范围1e3,好直接暴力就行(
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int a[N];
bool vis[N];
int main()
{
int n;
cin >> n;
a[0] = a[1] = 1;
for(int i = 2; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
for(int k = 1; i - 2 * k >= 0; k++)
{
vis[2 * a[i - k] - a[i - 2 * k]] = 1;
}
for(a[i] = 1; vis[a[i]]; a[i]++);
}
cout << a[n] << endl;
return 0;
}
B-Gene Tree
题意
思路
代码
I-Thread Knots
题意
给定一串全部在x轴上的线,保证没有一条线完全包含另一条线,要求你用绳结把他们绑在一起,问所有绳结间距的最小值最大为多少
思路
二分枚举绳结的间距即可,挺签到的没人写,拿了个一血(
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
struct node
{
ll x;
ll l;
bool operator < (const node& obj) const
{
return x < obj.x;
}
} a[N];
int n;
bool ok(ll len)
{
ll now = a[0].x;
for(int i = 1; i < n; i++)
{
now += len;
if(now < a[i].x)
now = a[i].x;
else if(now > a[i].x + a[i].l)
return 0;
}
return 1;
}
int main()
{
scanf("%d", &n);
ll l = INF, r = 0;
for(int i = 0; i < n; i++)
{
scanf("%lld%lld", &a[i].x, &a[i].l);
r = max(r, a[i].x + a[i].l);
l = min(l, a[i].x);
}
r = r - l;
l = 1;
sort(a, a + n);
ll ans;
while(r >= l)
{
ll mid = (r + l) >> 1;
if(ok(mid))
{
l = mid + 1;
ans = mid;
}
else
r = mid - 1;
}
printf("%lld\n", ans);
return 0;
}
J-Triangulation
题意
对于 n n n 边形,你可以把它分成若干个三角形,定义两个三角形的距离为两个三角形中间间隔了多少三角形,给定 n n n ,求 n n n 边形分成若干三角形后,三角形间的最大距离的最小值是多少。
思路
可以发现最优解就是如下图的构造:
所以 n n n 边形的最大距离最小值就是 a n = ( a n + 1 ) / 2 + 2 a_n = (a_n + 1) / 2 + 2 an=(an+1)/2+2。
代码
放个队友优美的代码(
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[1000005];
int main(){
int n;
cin >> n;
dp[4] = 1;
for(int i = 5 ; i <= n ; i++)dp[i] = dp[(i + 1) / 2] + 2;
cout << dp[n];
}
L-What’s Mine is Mine
题意
给定 m m m 种矿以及他们的价格和 n n n 次矿物出现时间(开始时间、结束时间、哪种矿物),一旦决定挖这种矿就必须从头到尾挖,并且一个时间只能挖一个矿,问最大收益。( ∑ i = s t a r t e n d ( p r i c e t ) = ( e n d − s t a r t ) ∗ p r i c e t \sum_{i = start}^{end}(price_t) = (end - start) * price_t ∑i=startend(pricet)=(end−start)∗pricet)
思路
简单dp,递推式如下:
d
p
e
=
m
a
x
(
d
p
e
,
d
p
s
+
(
e
−
s
)
∗
p
r
i
c
e
t
)
dp_e = max(dp_e, dp_s + (e - s) * price_t)
dpe=max(dpe,dps+(e−s)∗pricet)
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e4 + 10;
const int M = 1e2 + 10;
int co[M];
struct node
{
int s, e, t;
bool operator < (const node& obj) const
{
if(s == obj.s)
return e < obj.e;
return s < obj.s;
}
}a[N];
int dp[N];
int main()
{
int m, n, ans = 0;
cin >> m >> n;
for(int i = 1; i <= m; i++)
{
cin >> co[i];
}
for(int i = 0; i < n; i++)
{
cin >> a[i].s >> a[i].e >> a[i].t;
}
sort(a, a + n);
for(int i = 0; i < n; i++)
{
int e = a[i].e;
int s = a[i].s;
int t = a[i].t;
for(int i = 0; i < s; i++)
dp[s] = max(dp[s], dp[i]);
dp[e] = max(dp[e], dp[s] + (e - s) * co[t]);
ans = max(ans, dp[e]);
}
cout << ans << endl;
return 0;
}