Codeforces Round 983 (Div. 2)
A
最坏的情况就是所有开着的开关尽可能配对
最好的情况就是所有开着的开关尽可能不配对
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N=1e6+10;
const int mod=998244353;
const int INF = 0x3f3f3f3f;
const ll INFll = 0x3f3f3f3f3f3f3f3f;
#define endl "\n"
//vector<vector<int>>adj(N);
void solve()
{
int n; cin >> n;
int sum = 0;
for(int i = 1; i <= 2 * n; i ++) {
int x; cin >> x;
sum += x;
}
cout << sum%2 << " ";
if(sum > n) sum -= 2 * (sum - n);
cout << sum << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cout << setprecision(11) << fixed;
int t;t=1;
cin>>t;
for(int i=1;i<=t;i++){
//printf("Case %d: ",i);
solve();
}
}
B
分析
首先要保证
当
直接使这个左右区间数量为1
现在就只有三个区间,"左","中", "右".
只剩一个要求了,所有区间的长度为奇数,第一轮构造可以保证 |中| 是奇数.
又因为题目保证
实际上 奇 = 偶 + 奇 + 偶 或者 奇 = 奇 + 奇 + 奇,
这两种情况会交替出现,加上边界判断,可以让这个枚举的复杂度降到
n = 1 时不可能有3个区间,要特判
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N=1e6+10;
const int mod=998244353;
const int INF = 0x3f3f3f3f;
const ll INFll = 0x3f3f3f3f3f3f3f3f;
#define endl "\n"
//vector<vector<int>>adj(N);
void solve()
{
int n, k;
cin >> n >> k;
int len = 0;
if(n == 1) {
cout << 1 << endl;
cout << 1 << endl;
return;
}
while(1) {
if(k - len < 1 || k + len > n) break;
int l = k - 1 - len ;
int r = n - k - len;
// cout << l << " " << r << endl;
if(l%2 && r%2) {
cout << 3 << endl;
cout << 1 << " " << l + 1 << " " << n - r + 1 << endl;
return;
}
len ++;
}
cout << "-1" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cout << setprecision(11) << fixed;
int t;t=1;
cin>>t;
for(int i=1;i<=t;i++){
//printf("Case %d: ",i);
solve();
}
}
C
分析
题目要求任选三个数都可以组成非退化三角形,所以最后所有数的取值都一个离散区间内,这个区间的要求是
那么在这个区间任选
所有将所有数排序,枚举所有数做区间最小值时,最大值可以取到多少,不在这个区间内的数个数就是需要的操作次数。
如何求右端点呢,显然可以二分,
这里提供一个双指针做法,因为随着最小值增大,最大值必然不减
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N=1e6+10;
const int mod=998244353;
const int INF = 0x3f3f3f3f;
const ll INFll = 0x3f3f3f3f3f3f3f3f;
#define endl "\n"
//vector<vector<int>>adj(N);
void solve()
{
int n; cin >> n;
vector<int> a(n);
for(int i = 0; i < n; i ++) cin >> a[i];
sort(a.begin(), a.end());
int ans = 0;
int r = 0;
for(int l = 0; l < n - 1; l ++) { // 区间为[l,r)
while(r < n && a[l] + a[l + 1] > a[r]) r ++;
ans = max(r - l, ans);
}
cout << n - ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cout << setprecision(11) << fixed;
int t;t=1;
cin>>t;
for(int i=1;i<=t;i++){
//printf("Case %d: ",i);
solve();
}
}
D
分析
题目明确表明去掉
同时
根据
接下来就很好办了,所有点从小到大枚举,首先通过
从第二层开始,每次判断当前这个点是否挂在这个上一层某个点下方,
根据父节点不减和每个父节点最多一个儿子两个条件
用双指针优化这个操作
代码中
因为每次只涉及到相邻2层的关系, 用了个类似dp中滚动数组的方式开了2个数组
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N=1e6+10;
const int mod=998244353;
const int INF = 0x3f3f3f3f;
const ll INFll = 0x3f3f3f3f3f3f3f3f;
//vector<vector<int>>adj(N);
int ask(int a, int b) {
int ans;
cout << "? " << a << " " << b << endl;
cin >> ans;
return ans;
}
void solve()
{
int n;
cin >> n;
vector<int>p(n, 0);
vector<int>fa,fa2;
p[1] = 0;
int i;
for(i = 2; i < n; i ++) {
if(ask(1, i) == 0) {
p[i] = 1;
fa.push_back(i);
i ++;
break;
}
p[i] = 0;
fa.push_back(i);
}
int j = 0;
for(; i < n ; i ++) {
while(j < (int)fa.size() && ask(fa[j], i) == 1) {
j ++;
}
if(j >= (int)fa.size()) {
swap(fa, fa2);
fa2.clear();
i --; // 注意这个地方,因为上一层点用完了才停了下来,并不是找到了p[i]
j = 0;
} else {
p[i] = fa[j];
fa2.push_back(i);
j ++;
}
}
cout << "! ";
for(int i = 1; i < n; i ++) cout << p[i] << " "; cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cout << setprecision(11) << fixed;
int t;t=1;
cin>>t;
for(int i=1;i<=t;i++){
//printf("Case %d: ",i);
solve();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具