牛客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)所以不用管加上它是否平衡。
小 L 为了干净只会左手拿湿垃圾,右手拿干垃圾,所以这一段垃圾的干垃圾数
量一定要等于湿垃圾,不然小 L 就会因不平衡而摔死(误),但当小 L 看到一
堆排列整齐垃圾时,他就懵逼了,而且还有好多的人继续来扔垃圾,而且只会
扔到垃圾堆的前面和后面,小 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
来源:牛客网
对于一排鸽子,每个鸽子有一个鸽值
定义某一区间内鸽子的鸽子的程度为这段区间内鸽值的最大值
定义某一区间内鸽子的不鸽的程度位这段区间内鸽值的或
现在你需要某一只鸽子代替你去做户外的事情,但是只有一段区间内的鸽子的
不鸽程度大于这段区间内鸽子程度时,这些鸽子才愿意出动
那么每次选定一只鸽子,请你回答:最少要同时出动多少只鸽子?
我需要想一会