题解:AT_agc003_e [AGC003E] Sequential operations on Sequence
对于两个相邻的操作,如果后一个更小,它会把前面的部分截断,上一个操作就没有用了。这样不断消去,最终操作序列严格递增,可以用单调栈维护,计入
考虑从后向前累计每个操作区间在最后用了多少次,设为
设剩余部分
因为取模每次至少减半只有
#include <bits/stdc++.h>
using namespace std;
long long a[100005],b[100005],d[100005],cnt[100005],len;
int main()
{
int q;
scanf("%lld%d",&a[0],&q);
for(int i=1;i<=q;i++)
scanf("%lld",&a[i]);
stack <int> stk;
for(int i=0;i<=q;i++)
{
while(!stk.empty()&&a[i]<=a[stk.top()])
stk.pop();
stk.push(i);
}
int len=stk.size();
for(int i=len;i>0;i--)
{
b[i]=a[stk.top()];
stk.pop();
}
cnt[len]=1;
for(int i=len;i>1;i--)
{
cnt[i-1]+=cnt[i]*(b[i]/b[i-1]);
long long r=b[i]%b[i-1];
while(r!=0)
{
int pos=upper_bound(b+1,b+len+1,r)-b-1;
if(pos==0)
{
d[1]+=cnt[i];
d[r+1]-=cnt[i];
break;
}
cnt[pos]+=cnt[i]*(r/b[pos]);
r%=b[pos];
}
}
for(int i=1;i<=b[1];i++)
{
d[i]+=d[i-1];
printf("%lld\n",cnt[1]+d[i]);
}
for(int i=b[1]+1;i<=a[0];i++)
puts("0");
return 0;
}