T3咕了,不太会,剩下的写一写思路
淘淘蓝蓝之地主的硬币
题面:
淘淘是远近有名的一位大地主,他善待农民,心地善良。 这一次,他雇佣了一群农民为他耕地。为了节省时间,他准备了许多钞票和一块大面包。 对于每一个农民,他既可以支付一张钞票,也可以选择把大面包给对方。得到了报酬的农民将立刻开始工作。 注意,一张钞票只能给一个农民,但面包是可以等那个农民干完活之后马上传递别的农民吃。同一个时刻可以有很多个农民在工作。 身为一个大地主,淘淘自然希望农民们可以早点完成工作。现在,告诉了你淘淘钞票的数量、农民的数量以及每一个农民耕地所需要花费的时间,请你求出所有农民完成工作的最少时间。
输入格式:
本题采用多组读入测试 第一行一个整数 T ,表示一共有 T 组数据。 接下来,一共 T 组数据,每组占据两行,前一行包含两个非负整数 n , k , 分别表农民数量和钞票数量。 后一行包含 n 个正整数 a1,a2,……an, ai 表示第 i 个农民完成工作的时间。
思路:显然是道贪心水题
易知把几张钞票给了需要时间最多的几个人,然后剩下的人开始轮流分配面包即可
细节优化:
1.要比较n与k的大小关系,若 n < k 一定要特判,不然会枚举到数组a[n]后面的元素
2.要比较排序后的a[1]与sum的大小,要让ans=max(a[1],sum);
淘淘蓝蓝喜欢01串
题面:
题目描述
淘淘蓝蓝有⼀个由 n 个字符组成的字符串 。每个字符为 0 或 1 。
淘淘蓝蓝可以对字符串执⾏操作。每个操作包括两个步骤:
从 1 到 |S| 之间选择⼀个整数 i,然后删除字符 si (字符串⻓度减⼩ 1,被删除的字符串右边的字符下标也减⼩ 1 );
如果字符串 s 不为空,则删除由相同字符组成的最⼤⻓度前缀(剩余字符的下标和字符串⻓度将减去删 除的前缀的⻓度)。
请注意,这两个步骤在每个操作中都是必需的,并且其顺序⽆法更改。
淘淘蓝蓝希望知道这个字符串最多能进⾏多少次操作。
请注意:如果某次操作只进⾏了⼀个步骤,也算作⼀次操作。
输入格式:
第⼀行⼀个整数 T ,表⽰数据组数。
对于每组数据
第⼀⾏⼀个整数 n , 表⽰字符串的长度,
接下来一行一个字符串 s 。
思路:
首先我们解释一下题意:
就是说给你一个01串
每次操作的意思是:
先删除一个元素(你可以指定)
然后删除开头的几个零或几个一
问你最多可以进行多少次操作
我们去想一件事:
就是我们先预处理出所有的相同字符的子串的尾位置
就比如说010001100 分成 0 1 000 11 00 (假如下标从一开始)所以就是记录为1 2 5 7 9
然后我们考虑,肯定一次操作会删除一个开头的子串
然后我们如果进行删除操作时,可以优先从每个长度大于一的子串中选择,从中删除一个数,这样可以使两次加起来才会删除一个子串,如果我们删除操作直接删除一个长度为一的子串的话,就等于是直接删除了一个子串,显然不如删除一个长子串中的数更优
所以我们先统计一下有几个长度大于一的子串,然后这些子串每一个都可以对应一整个操作,然后再看一看有哪些没有被处理的就是长度为1的子串,然后统计它们的个数tot,
ans=长度大于1的子段个数+tot/2+(tot/2==1)?0:1
最后贴一份代码吧:
#include <cstdio>
#include <algorithm>
#include <iostream>
const int N=1e5+10;
// #define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int t,n,now,cnt,i,pos,num[N];
int ceil(int x,int y){
if(x%y==0) return x/y;
return x/y+1;
}
bool vis[N];
char s[N];
int main(){
// open("str");
// freopen("1.out","w",stdout);
scanf("%d",&t);
while(t--){
int ans=0;
now=-1;cnt=0;
scanf("%d %s",&n,s+1);
for(i=1;i<=n;i++){
if(s[i]!=now){
num[++cnt]=1;
now=s[i];
}
else ++num[cnt];
}/*分块操作*/
for(i=1;i<=cnt;i++) vis[i]=0;//vis初始化为0
pos=1;
for(i=1;i<=cnt;i++){
while(vis[pos] || num[pos]==1) pos++;/*当该位置被搜过或者这一块只有一个数时,pos++*/
if(pos>cnt) break;
num[pos]--;
ans++;
vis[i]=1;
}
pos=0;
for(i=1;i<=cnt;i++) if(!vis[i]) pos++;
ans+=ceil(pos,2);//统计答案
printf("%d\n",ans);
}
return 0;
}
``