(赛后补题)G

编程入门 行业动态 更新时间:2024-10-25 12:24:27

(<a href=https://www.elefans.com/category/jswz/34/1760213.html style=赛后补题)G"/>

(赛后补题)G

纯纯大怨种是我,虽然这题两种方法都可以实现,但是二分的代码量很少,二十分钟就能写出来,而且很好调试,贪心就......写了将近4个小时才调出来的贪心写法,需要想的非常仔细,建议大家直接写二分吧!

这里还是两种写法都敲一下,毕竟是自己四个小时写出来的。

JB is playing a game. There are nn cities in the game, numbered as 1, 2, \cdots, n1,2,⋯,n. The ii-th city and the jj-th city are adjacent if and only if i = j - 1i=j−1 or i = j + 1i=j+1. Initially, some of the cities are occupied by JB.

The game runs in rounds. At the beginning of a round, each occupied city can mark at most one adjacent unoccupied city as the target of attack. At the end of the round, all the attack targets marked become occupied. The game ends when all the cities are occupied.

JB wants to occupy all the cities in minimum rounds. Can you help him?

Input

There are multiple test cases. The first line of the test case contains a positive integer TT, indicating the number of test cases. For each test case:

The first line contains an integer nn (1 \le n \le 10^61≤n≤106), indicating the number of cities.

The next line contains a string ss of length nn. It's guaranteed ss only contains '0' and '1'. The ii-th character describes the initial state of the ii-th city: if s_i =si​= '1', the ii-th city is occupied by JB initially. Otherwise, the ii-th city is not occupied initially.

It's guaranteed that the sum of nn over all the test cases doesn't exceed 10^6106. It's also guaranteed that there is at least one '1' in ss.

题意,给你一串01序列,0表示当前位置没有被攻占,1表示当前位置可以被攻占,每分钟可以让每个1选择一个方向攻占一个0,问你最短时间把所有的都变成1;

思路:首先是二分,二分需要的时间,然后判断这个时间是否所有的0都可以被攻占,最主要的就是这个check函数了, 我们需要提前把所有0的左右两个方向离他最近的第一个1的位置记录一下,然后就可以开始判断了, 如果两边的1都满足条件,首先选择左边的。贪心策略因为右边的要让给其他的0来选。

上代码

#include <bits/stdc++.h>
using namespace std;
const int N=2000010;
char a[N];
int l[N],r[N];
int n;
int f[N];
bool check(int x)
{for(int i=1;i<=n;i++)f[i]=0;for(int i=1;i<=n;i++){if(a[i]=='1')continue;if(x>=min(i-l[i],r[i]-i)+1)continue;if(l[i]>=1&&l[i]<=n&&!f[l[i]]&&x>=i-l[i]){f[l[i]]=1;continue;}else if(r[i]>=1&&r[i]<=n&&!f[r[i]]&&x>=r[i]-i){f[r[i]]=1;continue;}return  false;}return true;
}
int erfen(int l,int r)
{while(l<r){int mid=l+r>>1;if(check(mid))r=mid;else l=mid+1;}return l;
}
int main()
{int t;cin>>t;while(t--){scanf("%d",&n);getchar();for(int i=1;i<=n;i++){scanf("%c",&a[i]);}int now=-1e9;for(int i=1;i<=n;i++){l[i]=now;if(a[i]=='1') now=i;}now=1e9;for(int i=n;i>=1;i--){r[i]=now;if(a[i]=='1') now=i;}printf("%d\n",erfen(0,n));}return 0;
}

 贪心:

其实思路和二分一样,只不过变成了计算最短时间的过程。

我这里写的是先分块,将连续的1和连续的0都分成单个元素。

本质都一样的

然后要先特判全都是1的情况,直接输出0;

#include <bits/stdc++.h>
using namespace std;
const int N = 1001010;
char a[N];
int n0[N];
int n1[N];
int main()
{int n;int T;scanf("%d", &T);while (T--){scanf("%d", &n);getchar();int flag = 0;int p = 0;int q = 0;for (int i = 1; i <= n; i++){scanf("%c", &a[i]);if (a[i] == '0')flag = 1;}if (flag == 0){printf("0\n");continue;}int cnt0 = 0, cnt1 = 0, num = 0;flag = -1;if (a[1] == '0')n1[++cnt1] = 0;for (int i = 1; i <= n; i++){if (a[i] == '0'){if (flag == 0 || flag == -1){flag = 0;num++;}else if (flag == 1){flag = 0;n1[++cnt1] = num;num = 1;}}else{if (flag == 1 || flag == -1){num++;flag = 1;}else if (flag == 0){flag = 1;n0[++cnt0] = num;num = 1;}}}if (flag == 0)n0[++cnt0] = num;else if (flag == 1)n1[++cnt1] = num;if (a[n] == '0')n1[++cnt1] = 0;for (int i = 1; i <= cnt1; i++){if (i == 1 && n1[i] >= 1)n0[i]--;else if (i == cnt1 && n1[i] >= 1)n0[i - 1]--;else if (n1[i] > 1){n0[i - 1]--;n0[i]--;}}for (int i = 2; i < cnt1; i++){if (n1[i] != 1)continue;if (i == 2 && n1[1] == 0 && n1[i + 1] != 0){if (n0[1] >= (n0[2] + 1) / 2)n0[1]--;elsen0[2]--;continue;}else if (i == cnt1 - 1 && n1[cnt1] == 0 && n1[i - 1] != 0){if ((n0[i - 1] + 1) / 2 >= n0[cnt1 - 1])n0[i - 1]--;elsen0[cnt1 - 1]--;continue;}if (n1[i] == 1){if (n0[i - 1] >= n0[i])n0[i - 1]--;elsen0[i]--;}}int maxx = 0;if (n1[1] == 0)maxx = max(maxx, n0[1]);elsemaxx = max(maxx, (n0[1] + 1) / 2);if (n1[cnt1] == 0)maxx = max(maxx, n0[cnt1 - 1]);elsemaxx = max(maxx, (n0[cnt1 - 1] + 1) / 2);for (int i = 2; i <= cnt1 - 2; i++)maxx = max(maxx, (n0[i] + 1) / 2);printf("%d\n", maxx + 1);}return 0;
}

更多推荐

(赛后补题)G

本文发布于:2024-02-14 15:46:52,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1764228.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:赛后

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!