A. United We Stand
code
const int N = 1e6 + 10;
int a[N];
int n;
vector<int> b, c;
void solve(){
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> a[i];
sort(a + 1, a + 1 + n);
b.clear();
c.clear();
for(int i = 1; i <= n; i ++){
if(a[i] != a[n])
b.pb(a[i]);
else
c.pb(a[i]);
}
if(b.size() == n || !b.size())
cout << -1 << endl;
else{
cout << b.size() << ' ' << c.size() << endl;
for(auto i : b) cout << i <<' ';
cout << endl;
for(auto j : c) cout << j << ' ';
cout << endl;
}
}
B. Olya and Game with Arrays
code
void solve(){
int n;
cin >> n;
vector<int> a[n + 1], b;
ll ans = 0, minn = LNF;
for(int i = 1; i <= n; i ++){
int m; cin >> m;
for(int j = 1; j <= m; j ++){
int k; cin >> k;
a[i].pb(k);
}
sort(a[i].begin(), a[i].end());
ans += a[i][1];
minn = min(minn, a[i][1]);
b.pb(a[i][0]);
}
sort(b.begin(), b.end());
cout << ans - minn + b[0] << endl;
}
C. Another Permutation Problem
思路:
这个东西一眼是一个单峰函数,那么就可以二分
打表发现,峰值时,是一个递增的排列,后面的几个数字反转的结果
然后就可以二分这个后缀的长度
(我不会二分,二分边界调一万年,就范围内暴力check了)
code
int n;
int check(int mid){
ll res = 0;
for(int i = 1; i < mid; i ++)
res += i * i;
int l = mid, r = n;
int maxn = 0;
while(l <= r){
if(l == r)
res += l * r;
else
res += l * r * 2;
maxn = max(maxn, l * r);
l ++, r --;
}
return res - maxn;
}
void solve(){
cin >> n;
int l = 1, r = n;
while(r - l >= 3){
int midl = (l + l + r) / 3, midr = (l + r + r) / 3;
if(check(midl) < check(midr))
l = midl;
else r = midr;
}
int ans = 0;
for(int i = l; i <= r; i ++)
ans = max(check(i), ans);
cout << ans << endl;
}
D. Andrey and Escape from Capygrad
思路:首先可以发现,
[
l
,
r
]
[l,r]
[l,r]中的
r
r
r 是没啥用的,
[
a
,
b
]
[a,b]
[a,b] 中的
a
a
a 是没啥用的
这样的话,就把区间
[
l
,
b
]
[l,b]
[l,b] 当作一个可行区间,sort之后去二分就可以了
(全场写了两个二分,幸亏这个二分不用手写,哭了,真不会写二分)
code
const int N = 1e6 + 10;
PII a[N];
vector<PII> v;
int n;
void solve(){
cin >> n;
v.clear();
for(int i = 1; i <= n; i ++){
int l, r, L, R;
cin >> l >> r >> L >> R;
a[i] = {l, R};
}
sort(a + 1, a + 1 + n);
int l = LNF, r = 0;
for(int i = 1; i <= n; i ++){
if(a[i].x > r){
v.pb({l, r});
l = a[i].x;
}
r = max(r, a[i].y);
}
v.pb({l, r});
int q;
cin >> q;
while(q --){
int k; cin >> k;
PII s = {k, LNF};
auto idx = upper_bound(v.begin(), v.end(), s);
if(idx == v.begin())
cout << k << ' ';
else
cout << max((*(-- idx)).y, k) << ' ';
}
cout << endl;
}
E. Maximum Monogonosity
思路:
把
a
b
s
(
s
1
i
−
s
2
i
)
abs(s1_i-s2_i)
abs(s1i−s2i) 变成
m
a
x
(
s
1
i
−
s
2
i
,
s
2
i
−
s
1
i
)
max(s1_i - s2_i, s2_i-s1_i)
max(s1i−s2i,s2i−s1i) 乍一看可能觉得没区别,但是转换成这个样子就可以去dp了
所以
f
i
j
f_{ij}
fij 就表示前
i
i
i 个中选
j
j
j 个的最大花费
那么可以分成四种情况
s
1
i
+
s
2
i
s1_i+s2_i
s1i+s2i
s
1
i
−
s
2
i
s1_i-s2_i
s1i−s2i
−
s
1
i
+
s
2
i
-s1_i+s2_i
−s1i+s2i
−
s
1
i
+
s
2
i
-s1_i+s2_i
−s1i+s2i
我令
i
d
id
id 表示
i
d
=
i
−
j
id=i-j
id=i−j 所以,
a
i
d
a_{id}
aid 表示前
i
i
i 个数中选
j
j
j 个然后加上
s
1
i
+
s
2
i
s1_i+s2_i
s1i+s2i 的最大值
同理
b
i
d
,
c
i
d
,
d
i
d
b_{id},c_{id},d_{id}
bid,cid,did
所以状态转移式为
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
]
[
j
]
,
a
[
i
d
]
−
s
1
[
i
]
−
s
2
[
i
]
,
b
[
i
d
]
−
s
1
[
i
]
+
s
2
[
i
]
,
c
[
i
d
]
+
s
1
[
i
]
−
s
2
[
i
]
,
d
[
i
d
]
+
s
1
[
i
]
+
s
2
[
i
]
)
f[i][j] = max(f[i][j], a[id] - s1[i] - s2[i],b[id] - s1[i] + s2[i], c[id] + s1[i] - s2[i], d[id] + s1[i] + s2[i])
f[i][j]=max(f[i][j],a[id]−s1[i]−s2[i],b[id]−s1[i]+s2[i],c[id]+s1[i]−s2[i],d[id]+s1[i]+s2[i])
code
const int N = 3010;
ll a[N], b[N], c[N], d[N];
ll s1[N], s2[N];
ll f[N][N];
int n, k;
void solve(){
cin >> n >> k;
for(int i = 1; i <= n; i ++) cin >> s1[i];
for(int i = 1; i <= n; i ++) cin >> s2[i];
for(int i = 0; i <= n; i ++)
for(int j = 0; j <= k; j ++)
f[i][j] = 0;
for(int i = 0; i <= n; i ++)
a[i] = b[i] = c[i] = d[i] = -LNF;
a[0] = s1[1] + s2[1];
b[0] = s1[1] - s2[1];
c[0] = - s1[1] + s2[1];
d[0] = - s1[1] - s2[1];
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= k; j ++)
f[i][j] = max(f[i - 1][j], f[i - 1][j - 1] + 2 * abs(s1[i] - s2[i]));
for(int j = 0; j <= min(i, k); j ++){
int id = i - j;
f[i][j] = max(max(f[i][j],
a[id] - s1[i] - s2[i]),
max({b[id] - s1[i] + s2[i],
c[id] + s1[i] - s2[i],
d[id] + s1[i] + s2[i]}));
}
for(int j = 0; j <= min(i, k); j ++){
int id = i - j;
a[id] = max(a[id], f[i][j] + s1[i + 1] + s2[i + 1]);
b[id] = max(b[id], f[i][j] + s1[i + 1] - s2[i + 1]);
c[id] = max(c[id], f[i][j] - s1[i + 1] + s2[i + 1]);
d[id] = max(d[id], f[i][j] - s1[i + 1] - s2[i + 1]);
}
}
cout << f[n][k] << endl;
}