题目描述:
给定一个初始为空的数组,你需要执行q次操作:对于每次操作,给定两个非负整数t和v,从数组的末尾移除t个元素,然后将v添加到数组的末尾。保证在执行操作之前,t不会超过数组的长度。
在每次操作之后,令当前数组为a1, a2, …, an,找到s1, s2, …, sn的和,其中si = ai + ai+1 + … + an表示从位置i开始的后缀和。
由于答案可能非常大,输出结果模1000000007。
输入描述:
第一行包含一个整数q(1 ≤ q ≤ 5 × 10^5),表示操作的数量。
接下来的q行,每行包含两个非负整数t和v(0 ≤ v ≤ 10^9),描述一个操作,其中t不会超过在本次操作前数组的长度。
输出描述:
输出q行,每行包含一个整数,表示每次操作后的答案。
示例1:
输入:
5
0 1
0 2
1 3
0 6
2 100000
输出:
1
5
7
25
200001
说明:
在第一次操作后,数组变为[1],后缀和数组为[1],后缀和之和为1。
在第二次操作后,数组变为[1, 2],后缀和数组为[3, 2],后缀和之和为5。
在第三次操作后,数组变为[1, 3],后缀和数组为[4, 3],后缀和之和为7。
在第四次操作后,数组变为[1, 3, 6],后缀和数组为[10, 9, 6],后缀和之和为25。
在第五次操作后,数组变为[1, 100000],后缀和数组为[100001, 100000],后缀和之和为200001。
示例2:
输入:
1
0 1000000000
输出:
1000000000
思路:
如果遇到0,我们就给数组末尾添加该数字,遇到其他数字,就在末尾删除几个数字,计算其后缀和,输出后缀和值
例如:
示例1:
输入:0 1---0 2----1 3---0 6---2 100000
我们遇到0,则数组为[1];后缀和为[1],值为1;数组长度为1
遇到0,则数组为[1,2];后缀和为[1+2,2],值为1+2+2;数组长度为2
遇到1,则删除后一位为[1,3],后缀和为[1+3,3],值为1+3+3,数组长度为2
遇到0,数组为[1,3,6],后缀和为[1+3+6,3+6,6],值为1+3+3+6+6+6,数组长度为3
遇到2,则删除后两位,数组为[1,100000],后缀和为[1+100000,100000],值为1+100000+100000,数组长度为2
我们用a数组来存储数组长度的后缀值
a[0]=0; k=1(数组长度为1)a[1]=a[0]+1*v;数组长度为2,a[2]=a[1]+2*v; 遇到1,数组进行变换,返回到a[1]状态后再进行操作,k=k-t=k-1=2;a[2]=a[1]+2*v=1+2*3=7;遇到0,数组变成[1,3,6],数组长度为3,k=3;a[3]=a[2]+3*v=7+3*6=25
代码:
#include<stdio.h>
#define N 500000
#define modd 1000000007
int main(){
long long n;
scanf("%lld",&n);
long long i;
long long a[N+1];
a[0]=0;
long long t,v;
int k=1;
for(i=1;i<=n;i++){
scanf("%lld %lld",&t,&v);
if(t!=0){
k=k-t;
}
a[k]=(a[k-1]+k*v)%modd;
printf("%lld\n",a[k]);
k++;
}
}