【Day4】一名菜鸟ACMer的暑假训练
【Day4】一名菜鸟ACMer的暑假训练
CF构造题1200-1400
D. Districts Connection
https://codeforces.com/problemset/problem/1433/D
1200
pair<帮派,编号>排序
第一个帮派的第一个成员连向不同帮派的所有成员,
第一个帮派的其他成员连向任意一个不同帮派的成员
#include <bits/stdc++.h>
using namespace std;
const int N = 5005;
typedef pair<int, int> pii;
pii a[N];
void solve () {
int n;
cin >> n;
for (int i = 1; i <= n; i ++) {
int x;
cin >> x;
a[i] = {x, i};
}
sort (a + 1, a + n + 1);
if (a[n].first == a[1].first) {
cout << "NO\n";
return ;
}
int i;
set <pii> s;
for (i = 2; i <= n; i ++)
if (a[i].first != a[1].first)
break;
//cout << "i=" << i << endl;
for (int j = i; j <= n; j ++)
s.insert ({a[1].second, a[j].second});
for (int j = i - 1; j > 1; j --)
s.insert ({a[j].second, a[i].second});
//for (auto j : s) cout << j.first << ' ' << j.second << endl;
if (s.size () != n - 1) cout << "NO\n";
else {
cout << "YES\n";
for (auto j : s) cout << j.first << ' ' << j.second << endl;
}
}
int main () {
int t;
cin >> t;
while (t --) {
solve ();
}
}
//pair<帮派,编号>排序
//第一个帮派的第一个成员连向不同帮派的所有成员,
//第一个帮派的其他成员连向任意一个不同帮派的成员
B. Random Teams
1300
https://codeforces.com/problemset/problem/478/B
阶梯型增长(故局部最大值即全局最大值)
minn:均摊 + 多出来的再均摊
maxn:1 1 1 ... n-m+1
#include <bits/stdc++.h>
#define int long long
using namespace std;
int count (int x) {
return (x - 1) * x / 2;
}
signed main () {
int n, m;
cin >> n >> m;
int x = n - m + 1;
int maxn = count (x);
int dx = n/m, cnt = n%m;
//cout << dx << ' ' << cnt << endl;
int minn = (m - cnt) * count (dx) + cnt * count (dx + 1);
cout << minn << ' ' << maxn << endl;
}
//抽屉原理的裸题
//阶梯型增长(故局部最大值即全局最大值)
//minn:均摊 + 多出来的再均摊
//maxn:1 1 1 ... n-m+1
C. Social Distance
1300
https://codeforces.com/problemset/problem/1367/C
WA了贼多次,调了爆久
主要是情况和数量关系没有捋清楚:
对于任何一段连续0:
1. free的情况:第一个放1,后面每k+1长度内可以放一个1
2. 位于中间(左右必为1): (len-2k-1)/(k+1) + 1
3. 位于开头:len/(k+1) (由1 + (len-k-1)/(k+1)化简得来)
4. 位于结尾:len/(k+1)
(可以自己画些图来理解)
#include <bits/stdc++.h>
using namespace std;
int n, k;
string s;
void solve () {
cin >> n >> k >> s;
//对于任何一段连续0:
//位于中间(左右必为1): (len-2k)/(k+1)
//位于开头:len/(k+1)
//位于结尾:len/(k+1)
int len = 0, ans = 0, st = -1, ed = -1;
for (int i = 0; i < n; i ++) {
if (s[i] == '0') {
if (st == -1) st = i; //语法错误
ed = i, len ++;
}
else {
if (i == 0) continue;
// cout << "len=" << len << endl;
// cout << "st=" << st << ", ed=" << ed << endl;
if (st != 0 && ed != n-1) {
int dx = len - 2 * k;
if (dx > 0) ans += (dx - 1) / (k + 1) + 1;
}
else if (st == 0 || ed == n-1) {
ans += len / (k + 1); // 1 + (len-k-1)/(k+1)
}
st = ed = -1, len = 0;
}
}
if (ed == n-1) {
if (st == 0) ans += (len - 1) / (k + 1) + 1;
else ans += len / (k + 1);
}
cout << ans << endl;
}
int main () {
int t;
cin >> t;
while (t --)
solve ();
}
//每两个1之间至少隔k个0
//求还能最多放下多少个1
//统计每一段连续0的长度len
//len<k:必然放不下
//len==k:端点左右都无1,可以放下一个
//len>k:可放下len/(k+1)个
//上面这里错了,别看
// 对于任何一段连续0:
// free的情况:第一个放1,后面每k+1长度内可以放一个1
// 位于中间(左右必为1): (len-2k-1)/(k+1) + 1
// 位于开头:len/(k+1) (由1 + (len-k-1)/(k+1)化简得来)
// 位于结尾:len/(k+1)
kuangbin最短路
做了俩
群友问的一道题
https://ac.nowcoder.com/acm/problem/14596
不难。。但是我傻了
样例辅助理解:
#include <bits/stdc++.h>
using namespace std;
typedef pair <int, int> pii;
const int N = 1e5 + 5;
pii a[N];
int n, k;
void solve () {
vector <vector<int>> pos;
for (int i = 0; i < n; i ++) {
int x; cin >> x;
a[i] = {x, i};
}
sort (a, a + n); //连续段放在一起
int st = 0, ans = 0;
for (int i = 0; i < n; i ++) {
while (a[i].first != a[st].first ||((a[i].second - a[st].second) - (i - st) > k)) st ++;
ans = max (ans, i - st + 1);
}
cout << ans << endl;
}
int main () {
while (cin >> n >> k) {
solve ();
}
}
晚上vp了Codeforces Round #710 (Div. 3)
https://codeforces.com/contest/1506
脑子不太清醒。。输的一塌糊涂
明天再补题,明天一定好好学习