省赛组队赛暨省赛积分赛1
省赛组队赛暨省赛积分赛1
来写总结。自闭了我就是垃圾,越训越烂www
https://vjudge.net/contest/553737#overview
先把补了的题放上,剩下的明天看看能不能写。
D. Dasha and Very Difficult Problem
贪心构造,也是我唯一过的一题。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int n, L, R;
int a[N], l[N], r[N], ans[N];
pii c[N];
void solve () {
scanf ("%d%d%d", &n, &L, &R);
for (int i = 1; i <= n; i++) {
scanf ("%d", &a[i]);
l[i] = L - a[i], r[i] = R - a[i];
}
for (int i = 1; i <= n; i++) scanf ("%d", &c[i].first), c[i].second = i;
//c取最小的且比上一个大即可
sort (c + 1, c + n + 1);
int lst = 0;
for (int i = 1; i <= n; i++) {
int id = c[i].second, b = max (L, a[id] + lst + 1);
ans[id] = b;
lst = b - a[id];
}
int minn = ans[1], maxn = ans[1];
for (int i = 1; i <= n; i++) minn = min (minn, ans[i]), maxn = max (maxn, ans[i]);
if (maxn - minn > R - L) {
cout << -1;
return ;
}
int dx = minn - L;
for (int i = 1; i <= n; i++) cout << ans[i] - dx << ' ';
}
int main () {
solve ();
}
C. Chessboard
这个真的好可惜,当时急了,只想着最暴力的做法,明明那个n为奇数都已经标粗了还是没细想!!!还以为是状压之类的赛后补提发现只有两种最终局面,所以直接暴力check即可。。。真的心态出大问题。。。服了我自己
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 105, M = 205;
int a[5][N][N], n;
ll ans;
int seq[] = {0, 1, 2, 3};
void solve () {
//check两种局面
do {
//0开头(0,3是0开头偶0; 1,2是1开头偶1)
//1开头(0,3是1开头偶1; 1,2是0开头偶0)
ll cnt1 = 0, cnt2 = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int k = (i + j) & 1;
if (k == 0) { //偶
if (a[seq[0]][i][j] != 0) cnt1 ++;
else cnt2 ++;
if (a[seq[1]][i][j] != 1) cnt1 ++;
else cnt2 ++;
if (a[seq[2]][i][j] != 1) cnt1 ++;
else cnt2 ++;
if (a[seq[3]][i][j] != 0) cnt1 ++;
else cnt2 ++;
}
else {
if (a[seq[0]][i][j] != 1) cnt1 ++;
else cnt2 ++;
if (a[seq[1]][i][j] != 0) cnt1 ++;
else cnt2 ++;
if (a[seq[2]][i][j] != 0) cnt1 ++;
else cnt2 ++;
if (a[seq[3]][i][j] != 1) cnt1 ++;
else cnt2 ++;
}
}
}
ans = min (ans, min (cnt1, cnt2));
} while (next_permutation (seq, seq + 4));
}
int main () {
cin >> n;
ans = 4 * n * n + 1;
for (int k = 0; k < 4; k++) {
for (int i = 1; i <= n; i++) {
string s;
cin >> s;
for (int j = 1; j <= n; j++) {
a[k][i][j] = s[j-1] - '0';
}
}
//check内部有无冲突
}
solve ();
cout << ans << endl;
}
//其实终局是固定的,只有两种可能(奇数决定了0/1开头之后的局面是固定的),只需枚举判断记录最小值
J. The Parade
贪心,但是没贪对。
我原有的错误思路:先把整段的放了,然后剩余的和上一段拼凑。
实际上真正的贪心,本段先和上一段剩下来的拼凑,余数再继承。
这里面要细想一下逻辑,最好画个图辅助理解。。
也是最后把自己绕进去了还想了个dp啥的。。。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 30005;
ll n, k, a[N];
bool check (ll x) { //关键在于怎么放
//同一行中所有士兵的身高差不能超过 1
ll cnt = 0, res = 0; //看行数是否>=k, res为上行的遗留
for (int i = 1; i <= n; i++) { //先放小的,然后调整空间更多一些?
if (a[i] + res < x) {
res = a[i] % x;
}
else {
cnt += (a[i] + res) / x;
res = (a[i] + res) % x;
}
}
return cnt >= k;
}
void solve () {
scanf ("%lld%lld", &n, &k);
ll l = 0, r = 0, sum = 0;
for (int i = 1; i <= n; i++) scanf ("%lld", &a[i]), sum += a[i];
//二分该单最大数量
r = sum / k;
while (l < r) {
ll mid = l + r + 1 >> 1;
if (check (mid)) l = mid;
else r = mid - 1;
}
printf ("%lld\n", l * k);
}
int main () {
int t;
scanf ("%d", &t);
while (t --) solve ();
}
特别注意答案是有可能为0的!!!!
分类:
vjudge
, ACM - 基础 - 二分