题意:这个题说白了就是一个线段树区间跟新的问题,只不过是刻意加大了难度。操作一:从x-n每个点加k+td(t=0,1,2……);操作二,输出某个点的值,并清0
题解:明显的线段树区间更新。每个点都加k这个简单。只不过延迟更新需要更新区间内的点加了多少次,就有点困难了,但是查询的时候只查一个点。所以可以一直把设计每个点的做区间记录下来,然后在查询的时候一起算 node[n]=(node[n]+(r*Time[n]-pos[n])*d%mod+sum[n])%mod;
就例如2-5,3-5,4-5都更新过,那么5这个点一定加了3+2+1次d,正好就是3*5-(2+3+4)=6;所以,问题解决!
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
ll a[100010],sum[100010*4],Time[100010*4],pos[100010*4];
ll node[100010*4];
int m,d;
void build(int l,int r,int n)
{
if(l==r){node[n]=a[l];return;}
int mid=(l+r)/2;
build(l,mid,n*2);build(mid+1,r,n*2+1);
}
void pushdown(int n,int l,int r)
{
if(l==r)
{
node[n]=(node[n]+(r*Time[n]-pos[n])*d%mod+sum[n])%mod;;
}
else
{
sum[n*2]+=sum[n];sum[n*2+1]+=sum[n];
pos[n*2]+=pos[n];pos[n*2+1]+=pos[n];
Time[n*2]+=Time[n];Time[n*2+1]+=Time[n];
}
sum[n]=0;pos[n]=0;Time[n]=0;
}
void update(int p,int q,int l,int r,int n,int y)
{
pushdown(n,l,r);
if(p<=l&&q>=r)
{
sum[n]+=y;
pos[n]+=p;
Time[n]+=1;
return;
}
int mid=(l+r)/2;
if(p>=mid+1)
update(p,q,mid+1,r,n*2+1,y);
else if(q<=mid)
update(p,q,l,mid,n*2,y);
else
{
update(p,q,l,mid,n*2,y);
update(p,q,mid+1,r,n*2+1,y);
}
}
ll query(int p,int q,int l,int r,int n)
{
pushdown(n,l,r);
if(l==r)
{
ll ret=node[n];
node[n]=0;
return ret;
}
int mid=(l+r)/2;
if(p>=mid+1)
return query(p,q,mid+1,r,n*2+1);
else
return query(p,q,l,mid,n*2);
}
int n;
int main()
{
int t,x,y,op;
scanf("%d",&t);
while(t--)
{
memset(sum,0,sizeof(sum));
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
update(x,n,1,n,1,y);
}
else
{
scanf("%d",&x);
printf("%lld\n",query(x,x,1,n,1));
}
}
}
return 0;
}