第一步:先看题
这道题其实也不能顺着题去想,要不然不是空间炸,就是时间炸,因为数据范围非常大!;题目:
P7870 「Wdoi-4」兔已着陆 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
第二步:细观察
这题目看起来和写作文一样,十分繁琐,让人头疼;所提要学会提取有用信息:
1.清兰使用河童的机器可以生产出各种各样颜色的团子。她发现,对于颜色为 𝑐 的团子,它的售价为 𝑐。同时,团子机器有个特性,那就是生产出来的团子的颜色必然是一段连续的整数。
2. 1 l r:团子机器生产出来了颜色为 𝑙,𝑙+1,⋯𝑟−1,𝑟l,l+1,⋯r−1,r 的团子。清兰将这些团子依次入栈。也就是在栈顶依次加入 𝑙,𝑙+1,𝑙+2,⋯𝑟−1,𝑟l,l+1,l+2,⋯r−1,r 。2 k:有一位客人想要购买 𝑘k 个团子。此时清兰会依次从栈顶取出 𝑘 个团子并售出。保证 𝑘 不大于当前栈内的团子个数。
3.
- 对于前 30%的数据,𝑛,𝑙,𝑟≤100n,l,r≤100。
- 对于另外 20% 的数据,𝑙=𝑟。
- 对于另外 20% 的数据,𝑘≤10。
- 对于 100% 的数据,1≤𝑛≤5×10的5次方,0≤𝑙≤𝑟≤10的6次方,1≤𝑘≤10的12次方。
事实上,善于观察和运用这些特殊情况和数据范围,有助于我们在考场上拿更多的分数。
第三步:理思路
如果想要拿到满分,那么这道题就不能把这些“团子”一个一个存进去,因为1≤𝑘≤10的12次方!!!;要把“团子”一批一批地放进去,建立一个栈,么一次存储都要把第一个的价格、最后一个的价格和这一批团子总数存进去;每一次取出,如果k大于最上面一批的数量,k就一直减去最上面一批的数量,把栈弹出一层,直到k比最上面一批的数量小为止,在计算卖不完一批“团子”的价格时,只需(第一个“团子”+第一个“团子”-需要的数量+1)*需要的数量/2就可以了,再把原先的弹掉,重新放进去剩余的;最后输出总价格。
第四步:看代码
#include<bits/stdc++.h>
using namespace std;
struct bz{
long long h,b,m;
};
long long n,l,r,zl,o,ti=1,ans;
stack<bz>stk;
bz k;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>zl;
if(zl==1){
cin>>l>>r;
stk.push(bz{r,l,r-l+1});
}else{
cin>>o;
ans=0;
while(o>stk.top().m){
ans+=(stk.top().b+stk.top().h)*stk.top().m/2;
o-=stk.top().m;
stk.pop();
}
cout<<((stk.top().h-o+1)+(stk.top().h))*o/2+ans<<endl;
k=bz{stk.top().h-o,stk.top().b,stk.top().m-o};
stk.pop();
if(k.m!=0){
stk.push(k);
}
}
}
return 0 ;
}
这下,问题应该就不大了,如果有更加简单的方法,欢迎评论;
第五步:点个赞再走吧