专栏文章
Atcoder ABC 393
题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miq8j662
- 此快照首次捕获于
- 2025/12/04 00:42 3 个月前
- 此快照最后确认于
- 2025/12/04 00:42 3 个月前
给出个点和条边的无向图,最少需要删除多少边使得这个图成为简单图, 即没有重边和自环。
- 遇到自环直接删除。
- 用记录重边
#include<bits/stdc++.h>
using namespace std;
map<pair<int, int>, int>mp;
// mp [{u,v}] -> u到v的边有没有出现过
int main(){
int n, m;
cin >> n >> m;
int ans = 0;
for(int i = 1; i <= m; i++){
int u, v;
cin >> u >> v;
//默认让小的点 连向大的点
if(u > v) swap(u, v);
if(u == v) ans++;
else if(mp.count({u, v})) ans++;
mp[{u, v}] = 1;
}
cout << ans << endl;
return 0;
}
先确定移动的位置,可以大胆猜一下,往哪个
1去靠。 显然往中间的1去靠,比边上的1会更优。类似中位数求最短距离一样。把所有是
1的位置都找出来,放入数组中,可以先求出中位数的位置。对于第个
CPP1,它贡献的答案为#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int n;
string s;
cin >> n >> s;
vector<int> pos;
for(int i = 0; i < n; i++)
if (s[i] == '1')
pos.push_back(i);
int cnt = pos.size();
if (cnt <= 1){
cout << 0 << endl;
return 0;
}
int mid = cnt / 2, ans = 0;
for (int i = 0; i < pos.size(); i++)
ans += abs(pos[mid] - (mid - i) - pos[i]);
cout << ans << endl;
return 0;
}
解法2:
考虑对
0的移动,对于第位上的0,统计左侧的个数为,右侧的个数为。最终的得到的字符串形状:
0...01...10..0,前面0的数量可能是个,后面0的数量可能是个。从左往右考虑`0',它对答案的贡献是
思路:考虑枚举最大公约数 ,再看 的倍数个数和 的关系,来决定 能不能作为答案。
做法:
-
统计数字的数量 ,表示数字的答案。
-
枚举当前最大公约数, 再枚举的倍数,得到原数组中有约数的数量为个。
-
若, 则说明一定能从原数组中选出k个数,使得他们的最大公约数至少为,所以可以把所有的倍数的答案更新为
-
考虑完所有的后,此时就是数字i的最优答案。
例如样例1:
3 4 6 7 12
== 时, 则当前算出
== 时,更新
== 时,更新
...
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 12e5 + 10;
int a[N], mp[N], ans[N];
signed main(){
int n, k;
cin >> n >> k;
int lim = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
mp[a[i]]++;
lim = max(lim, a[i]);
}
for(int d = 1; d <= lim; d++){
int cnt = 0;
for(int i = d; i <= lim; i += d)
cnt += mp[i];
if(cnt >= k){
for(int i = d; i <= lim; i += d)
ans[i] = d;
}
}
for(int i = 1; i <= n; i++)
cout << ans[a[i]] << endl;
return 0;
}
根据求的思想,设 为当前项时长度为 的序列末项最小值,
由于 具有递增性,每次二分查找在数组 中第一个大于等于 的位置更新。
离线查询,每次在对应的r的位置,二分求在当前状态下数组中最后一个不大于的位置需要即为答案。
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10, inf = 1e18;
int n, q, a[N], f[N];
struct node{
int id, r, x, ans;
}qry[N];
bool cmp(node A, node B){
return A.r < B.r;
}
bool cmp2(node A, node B){
return A.id < B.id;
}
signed main(){
scanf("%lld%lld", &n, &q);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for(int i = 1; i <= q; i++){
int r, x;
scanf("%lld%lld", &r, &x);
qry[i] = {i, r, x, 0};
}
sort(qry + 1, qry + q + 1, cmp);
for(int i = 1; i <= n; i++) f[i] = inf;
f[0] = 0;
for(int i = 1, j = 1; i <= n; i++){
int k = lower_bound(f, f + n + 1, a[i]) - f;
f[k] = min(f[k], a[i]);
while(j <= q && qry[j].r == i){
qry[j].ans = upper_bound(f, f + n + 1, qry[j].x) - f - 1;
j++;
}
}
sort(qry + 1, qry + q + 1, cmp2);
for(int i = 1; i <= q; i++)
printf("%lld\n", qry[i].ans);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...