牛客IOI周赛16-提高组

 

链接:https://ac.nowcoder.com/acm/contest/5388/A
来源:牛客网

给你一个边长为 n 的用硬币摆成的实心三角形,请问把他倒过来最少需要多少步?
我觉得这种题没什么好办法,就是找规律,多练习这种题就可能发现规律;一般找规律的题,就先暴力(枚举),再从枚举中推个公式;这道题根据数据就知道需要个公式;牛客上的题解写的很清楚;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=23333333333333333;
int main()
{
    ll n,t;
    cin>>t;
    while(t--)
    {
        cin>>n;
      
            __int128  t;
            t=n;
            t=t*(t+1)/6%mod;
            ll ans=t%mod;
            cout<<ans<<endl;
        
    }
}

链接:https://ac.nowcoder.com/acm/contest/5388/B
来源:牛客网

题目描述

现在小 L 要帮市民扔垃圾了!但为了方便,小 L 只会拿一段连续的垃圾,而且
小 L 为了干净只会左手拿湿垃圾,右手拿干垃圾,所以这一段垃圾的干垃圾数
量一定要等于湿垃圾,不然小 L 就会因不平衡而摔死(误),但当小 L 看到一
堆排列整齐垃圾时,他就懵逼了,而且还有好多的人继续来扔垃圾,而且只会
扔到垃圾堆的前面和后面,小 A 可没那么多时间,小 A 想知道每一个时间一次
最多能拿多少垃圾。

除了干垃圾,湿垃圾,还有可回收垃圾,可回收垃圾会被小 A 背在背上去卖钱
(误×2)所以不用管加上它是否平衡。
 刚开始想的暴力!数据显然过不去;对于W、D类似于括号匹配问题,只是不需要限制位置如何;则用前缀和,W代表1,R代表0,D代表-1;只用前缀和也是超时;
就要优化,类似于hash,则用一个桶;桶里面放的是,当前缀和值为k时,(在字符串中)位置为i
#include<bits/stdc++.h>
using namespace std;
const int maxn=2000000;
const int maxn1=2100000;
int sum[maxn1*2],op[maxn1],max1[maxn1*2],min1[maxn1*2];
char s[maxn1];
int add_litter[maxn1*2];
int main()
{
    int n,cnt=0;
    memset(min1,0x3f,sizeof(min1));
    cin>>n;
    cin>>s;
    for(int i=1;i<=n;i++)//n种操作
    {
        cin>>op[i];
        char ch;
        cin>>ch;
        if(op[i]==1) ++cnt;//cnt记录垃圾放在前面的操作次数
        if(ch=='W') add_litter[i]=1;
        else if(ch=='D') add_litter[i]=-1;
        else add_litter[i]=0;
    }
    int l=cnt+1,r=cnt+strlen(s);//l是初始输入数组的左端点,r为右端点
    for(int i=l;i<=r;i++)
    {
        if(s[i-l]=='W') sum[i]=1;
        else if(s[i-l]=='D') sum[i]=-1;
        else sum[i]=0;
        sum[i]+=sum[i-1];//前缀和
        max1[sum[i]+maxn]=i;//sum[i](前缀和)+maxn相当于对每个前缀和增加了maxn,防止出现负值,max1中记录的是前缀和为sum[i]+maxn的最大i值
    }
    for(int i=r;i>=l;i--)
        min1[sum[i]+maxn]=i;//记录值为sum[i]+maxn的最小i值
    int answer=0;
    min1[maxn]=l-1;
    for(int i=l-1;i<=r;i++)
        answer=max(answer,max1[sum[i]+maxn]-i);//max1中记录的最大位置k,即sum[k]+maxn=sum[i]+maxn,所以k-i为所能提的最大垃圾
    cout<<answer<<endl;
    for(int i=1;i<=n;i++)
    {
        if(op[i]==1)
        {
            l--;
            sum[l-1]=sum[l]-add_litter[i];
            min1[sum[l-1]+maxn]=l-1;
            max1[sum[l-1]+maxn]=max(l-1,max1[sum[l-1]+maxn]);
            answer=max(answer,max1[sum[l-1]+maxn]-(l-1));
        }
        else {
            r++;
            sum[r]=sum[r-1]+add_litter[i];
            max1[sum[r]+maxn]=r;
            min1[sum[r]+maxn]=min(min1[sum[r]+maxn],r);
            answer=max(answer,r-min1[sum[r]+maxn]);
        }
        cout<<answer<<endl;
    }
}

链接:https://ac.nowcoder.com/acm/contest/5388/C
来源:牛客网

对于一排鸽子,每个鸽子有一个鸽值
定义某一区间内鸽子的鸽子的程度为这段区间内鸽值的最大值
定义某一区间内鸽子的不鸽的程度位这段区间内鸽值的或
现在你需要某一只鸽子代替你去做户外的事情,但是只有一段区间内的鸽子的
不鸽程度大于这段区间内鸽子程度时,这些鸽子才愿意出动
那么每次选定一只鸽子,请你回答:最少要同时出动多少只鸽子?

 我需要想一会

 

posted @ 2020-05-04 23:16  SuccessfulRoad  阅读(219)  评论(0编辑  收藏  举报