Codeforces Round #436 div 2 A B C D 题解

来源:互联网 发布:几个淘宝号刷一天挣40 编辑:程序博客网 时间:2024/05/21 15:01

A:题意 给N个数 如果N只有两种相同数目的数字,输出YES,否则输出NO

思路:统计下数目就好了,水题


B:题意 给N个大写 /小写字母,选若干不同的小写字母,且小写字母之间不能有大写字母,问最多能选多少个小写字母

思路:设一个set<char>a[N],以大写字母为分界点,各部分用set存起来去重即可,输出大小最大的set,水题


C:题意:a距离来回k次,f处有加油站,问来回k次最少加油的次数

加油问题:给若干加油站的位置和能加的油量,起始油量及油量上限,终点的位置,问最少加多少次油

思路:经过一次加油站相当于获得了一次加油的机会。

pos:当前位置,初始化为0

tank:油量,初始化为b

jiayou[i]:  1<=i<=k+1, k+1个加油站的位置, 第k+1个加油站是终点

count:加油的机会,初始化为0;每经过一个加油站就+1,加一次油就-1;

ans:加油的次数,初始化为0

遍历所有加油站,对于每个加油站i,更新当前走过的距离d=jiayou[i]-pos,

若tank比d少,说明这段d距离的路不够油走(极端是刚好到不了i加油站),

就需要不断加油(每次加油更新变量tank count ans),加油直到tank比d大,那么就可以到达第i个加油站,到达后更新tank 和count即可

这里每个加油站加的油都固定的,(如果每个加油站油量不同,那么就需要优先队列来加前面1~i-1最大量的油站的油),简单题


D:题意,给N个数a[N],问最少改变多少个数,使得这N个数成为1~N的一个排列,并输出最小序的解。

思路:定义last数组 last[a[i]]=i,含义是a[i]最后出现的下标是多少,比如4 3 2 2 2,last[2]=5,last[3]=2,last[4]=1

显然,剩下的last[1]=0和last[5]=0,说明这个数列还缺少1和5,所以我们要让其中的两个数变成1,5,

而且发现最少修改的次数就是last[j]=0的j的个数

要输出最小序的解,所以设一个最小值优先的优先队列qq,把缺少的数字1,5存起来

遍历i=1~N,如果当前的i满足last[a[i]]!=i (即当前数字i不是a[i]=k最后出现的下标,即后面还有一样的k),

那么这个a[i]就可以修改成别的,修改成什么呢,我们要最小序,所以a[i]=qq.top();

上面的思路,举个例子:43222-》43122-》43152

当然,上面的思路有缺陷,如果是11223,缺少4,5,如果按照上面的思路就会改成4 1 5 2 3,这答案不对,应该把第二个1改成4才对,所以我们加两个条件:a[i]>qq.top()且qq不空,防止小的数提前被大的数修改掉,qq里比较大的数要在后面修改,

我们还需要一个vis数组,记录当前a[i]出现了这种情况,对于下一个a[i]=k就一定要用qq的数来修改(再不改就出现两个k了)

所以对于每次修改之后我们都要把修改后的vis[a[i]]设为1,说明我们已经存在a[i]了,后面再遇到a[i]就要用qq的数来修改了!


代码部分:

A:略

B:

set<char> a[205];char cs[205];int main(){int n;scanf("%d",&n);int num=0;getchar();for(int i=1; i<=n; i++)scanf("%c",&cs[i]);cs[0]='B';for(int i=1; i<=n; i++){if(isupper(cs[i])){continue;}if(!isupper(cs[i])){if(isupper(cs[i-1])){num++;}a[num].insert(cs[i]);}}if(num==0){printf("0\n");return 0;}int maxs=0;for(int i=1; i<=num; i++)maxs=max(maxs,(int)a[i].size());printf("%d\n",maxs);return 0;}
C:

int main(){ll a,b,f,k;cin>>a>>b>>f>>k;ll total=a*k;//length ll jiayou[10005];for(int i=1;i<=k;i++){if(i%2==1)jiayou[i]=f+(i-1)*a;elsejiayou[i]=2*a-f+(i-2)*a;}jiayou[k+1]=total;ll pos=0;//当前位置 ll tank=b;//当前油量 ll count=0;//加油站数目 ll ans=0;for(int i=1;i<=k+1;i++){ll d=jiayou[i]-pos;while(tank-d<0){if(count==0){printf("-1\n");return 0;}tank=b;ans++;count--;}tank-=d;pos=jiayou[i];count++;}cout<<ans<<endl;return 0;}
D:

#define scann(d) scanf("%d",&d)using namespace std;const int N=2e5+10;int n,a[N],last[N];bool vis[N];int main(){scann(n);for(int i=1; i<=n; i++){scann(a[i]);}for(int i=1; i<=n; i++){last[a[i]]=i;//数字a[i] 最后出现的下标 }priority_queue<int, vector<int>, greater<int> > h;for(int i=1; i<=n; i++){if ( last[i]==0 ) h.push(i);}for(int i=1; i<=n; i++){cout<<"last:"<<last[i]<<endl;}int ans=0;for(int i=1; i<=n; i++){if ( vis[a[i]] || (last[a[i]]!=i && !h.empty() && h.top()<a[i]) ){cout<<vis[a[i]]<<" "<<i<<"h.top:"<<h.top()<<endl;ans++;a[i]=h.top();h.pop();}vis[a[i]]=1;}printf("%d\n",ans);for(int i=1; i<=n; i++)printf("%d ",a[i]);return 0;}



原创粉丝点击