第 157 场周赛(8月3日)acwing

第 157 场周赛(8月3日)

5838. 四舍五入

给定一个两位正整数 n,请你输出其四舍五入到十位后的结果。

输入格式

一个正整数 n。

输出格式

一个整数,表示 n
四舍五入到十位后的结果。

数据范围

所有测试点满足 10≤n≤99

输入样例1:

13

输出样例1:

10

输入样例2:

98

输出样例2:

100

题解

额,送分

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    int x=n%10;
    if(x>=5)cout<<(n/10+1)*10<<endl;
    else cout<<n/10*10<<endl;
    return 0;
}
5839. 四舍五入II

给定一个实数,保证该数为正数,其小数点后至少包含一位非零的数字,且小数点后不含多余末尾 0。
如果将该实数转化为字符串,则字符串的长度为 n。
现在,你可以对该实数进行不超过 t 次(也可以零次)四舍五入操作。
每次操作可以将当前数四舍五入到小数点后的任意位置(也可以四舍五入到最接近的整数)。
例如,1.645 四舍五入到小数点后两位可以得到 1.65,1.141 四舍五入到小数点后一位可以得到 1.1,3.762 四舍五入到最接近的整数可以得到 4。
我们希望通过四舍五入操作,将给定实数变得尽可能大。
请你输出通过上述操作可以得到的最大可能值。

输入格式

第一行包含两个整数 n,t。
第二行包含给定正实数,保证其既包含整数部分也包含小数部分,且小数点后至少包含一位非零的数字,且小数点后不含多余末尾 0。如果将该实数转化为字符串,则字符串的长度为 n。

输出格式

输出一个实数,表示可以得到的最大可能值。
输出答案不应包含小数点后多余末尾 0。
如果答案是整数,则直接输出整数。

数据范围

前 4 个测试点满足 1≤n≤12,1≤t≤100。
所有测试点满足 1≤n≤2×105,1≤t≤109。

输入样例1:

6 1
10.245

输出样例1:

10.25

输入样例2:

6 2
10.245

输出样例2:

10.3

输入样例3:

3 100
9.2

输出样例3:

9.2

题解

这道题真的超级超级麻烦,思路简单,小数点后面找5然后进行调整,额细节太多写俩小时没写对。。。。。参考下别人代码吧,改对了来填坑

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int s[N];
int main()
{
    int tmp,n,t,i,num,m,flag=1;
    char ch;
    cin>>n>>t;
    for(i=0;i<n;i++)
    {
        cin>>ch;
        num=int(ch)-48;
        if(num>=0)s[i]=num; //'.'的ASCII码是46 如果ch不是'.',将num存入数组
        else tmp=i; //否则记录'.'的位置
    }
     m=tmp+1;//m记录小数点后一位的位置,即将开始对小数部分四舍五入
    while(t--)
    {
        //从第一位小数从前往后找第一个大于5的数,且要保证m所指位置不超过小数部分
        while(s[m]<5&&flag&&m<n-1) m++;
        //while后找到了第一个≥5的数,此时进行四舍五入后的数是最大的,后面就不需要再往后找≥5的数了,所以令flag=0
        flag=0;
        //如果小数部分没有数≥5,退出循环
        if(!flag&&s[m]<5)break;
        //如果是第一位小数≥于5,m指向个位数
        if(m-1==tmp)m-=2;
        //否则指向前一位小数
        else m--;
        //这条语句针对的是个位数,如果个位数原来是9,++后就是10,所以令其为0,十位数要+1,这个后面再处理
        if(s[m]+1==10)s[m]=0;
        //否则当前位置的数字+1
        else s[m]++;
    }

    //处理整数部分的进位问题,如果当前位数字为0,且不是最高位,继续循环
    while(s[m]==0&&m-1>=0)
    {
        //当前位的高位+1
        s[--m]++;
        //这里也是在判断是不是要进位
        if(s[m]==10)s[m]=0;
    }
    //如果第一位是0,说明是从9进位到了10,则整数最高位是1,输出1
    if(s[0]==0) cout<<"1";
    //输出所有数字,注意输出小数点
    for(int j=0;j<=m;j++)
    {
       if(j!=tmp)cout<<s[j];
       else cout<<".";
    }
    //整数部分缺0补0
    if(m>=0)
    {
    for(int j=m+1;j<tmp;j++)cout<<"0";
    }
    return 0;
}

作者:PPH
链接:https://www.acwing.com/solution/content/249970/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5840. 封印序列

给定一个长度为 n 的非负整数序列 a1,a2,…,an。
其中的所有元素将被逐个封印。
具体封印顺序可以用一个 1∼n 的排列 b1,b2,…,bn 来描述,第 i 个被封印的元素即为 abi。
你需要完成 n 个任务(编号 1∼n),其中第 i 个任务是:对于完成前 i 次封印的序列,请你找到序列中的一个连续子序列(可以为空),使得该子序列不含任何被封印的元素,且子序列内各元素之和尽可能大,输出这个子序列元素和的最大可能值。
空序列的元素和视为 0。

输入格式

第一行包含整数 n。
第二行包含 a1,a2,…,an。
第三行包含 b1,b2,…,bn。

输出格式

共 n 行,第 i 行输出第 i 个任务的结果。

数据范围

前 4 个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤105,0≤ai≤109,b1∼bn 是一个 1∼n 的排列。

输入样例1:

4
1 3 2 5
3 4 1 2

输出样例1:

5
4
3
0

输入样例2:

5
1 2 3 4 5
4 2 3 5 1

输出样例2:

6
5
5
1
0

输入样例3:

8
5 5 4 4 6 6 5 5
5 2 8 7 1 3 4 6

输出样例3:

18
16
11
8
8
6
6
0

题解

额,想不到
竟然需要并查集
然后我看有的人用线段树/线段数组也能写出来
不过对比了下好像老师给的方法还是最简单的。
https://www.acwing.com/video/5480/

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,p[100005],st[100005],s[100005];
int find(int x)
{
    if(x==p[x]) return p[x];
    return p[x]=find(p[x]); 
}

int a[100005],b[100005],ans[100005];
signed main()
{
	int i,j,k;
	cin>>n;
    for(i=1;i<=n+1;i++)    p[i]=i;
    for(i=1;i<=n;i++)  cin>>a[i];
    for(i=1;i<=n;i++)  cin>>b[i];
    int res=0;
    for(i=n;i>=1;i--)
    {
        ans[i]=res;
        int pos=b[i];
        st[pos]=1;
        s[pos]=a[pos];
        if(pos+1<=n&&st[pos+1]==1)
        {
            int x=find(pos),y=find(pos+1);
            p[x]=y;
            s[y]+=s[x];
        }
        if(pos-1>=1&&st[pos-1]==1)
        {
            int x=find(pos),y=find(pos-1);
            p[y]=x;s[x]+=s[y];
        }
        res=max(res,s[find(pos)]);
    }
    for(i=1;i<=n;i++)  cout<<ans[i]<<endl;
    return 0;
}

  • 23
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋洋的计算机刷题日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值