P1438 无聊的数列
题目背景
无聊的YYB总喜欢搞出一些正常人无法搞出的东西。有一天,无聊的YYB想出了一道无聊的题:无聊的数列。。。(K峰:这题不是傻X题吗)
题目描述
维护一个数列{a[i]},支持两种操作:
1、1 L R K D:给出一个长度等于R-L+1的等差数列,首项为K,公差为D,并将它对应加到a[L]~a[R]的每一个数上。即:令a[L]=a[L]+K,a[L+1]=a[L+1]+K+D,
a[L+2]=a[L+2]+K+2D……a[R]=a[R]+K+(R-L)D。
2、2 P:询问序列的第P个数的值a[P]。
输入输出格式
输入格式:
第一行两个整数数n,m,表示数列长度和操作个数。
第二行n个整数,第i个数表示a[i](i=1,2,3…,n)。
接下来的m行,表示m个操作,有两种形式:
1 L R K D
2 P 字母意义见描述(L≤R)。
题解:
差分,线段树
const int maxn = 1e6+11;
int sum[maxn],lazy[maxn];
void pushup(int i)
{
sum[i] = sum[i<<1]+sum[i<<1|1];
}
void pushdown(int i,int l,int r)
{
int mid = (l+r)>>1;
if(!lazy[i])return;
sum[i<<1] += (mid-l+1)*lazy[i];
sum[i<<1|1] += (r - mid)*lazy[i];
lazy[i<<1] += lazy[i];
lazy[i<<1|1] += lazy[i];
lazy[i] = 0;
}
void update(int i,int l,int r,int ql,int qr,int v)
{
if(ql <= l && qr >= r)
{
sum[i] += v*(r-l+1);
lazy[i] += v;
return;
}
pushdown(i,l,r);
int mid = (l+r)>>1;
if(ql<=mid)update(i<<1,l,mid,ql,qr,v);
if(qr>mid)update(i<<1|1,mid+1,r,ql,qr,v);
pushup(i);
}
int query(int i,int l,int r,int ql,int qr)
{
if(ql<=l && qr>=r)return sum[i];
pushdown(i,l,r);
int mid = (l+r)>>1;
int ans = 0;
if(ql<=mid)ans+=query(i<<1,l,mid,ql,qr);
if(qr>mid)ans+=query(i<<1|1,mid+1,r,ql,qr);
return ans;
}
int a[maxn];
int main()
{
int n,m;
cin>>n>>m;
rep(i,1,n+1)scanf("%d",a+i);
rep(i,1,m+1)
{
int op,l;scanf("%d%d",&op,&l);
if(op == 1)
{
int r,k,d;
scanf("%d%d%d",&r,&k,&d);
update(1,1,n,l,l,k);
if(r!=n)update(1,1,n,r+1,r+1,-(k+(r-l)*d));
if(r>l)update(1,1,n,l+1,r,d);
}
else
printf("%d\n",a[l]+query(1,1,n,1,l));
}
}
树状数组:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100010
using namespace std;
int a[MAXN][2],p[MAXN],n;
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int k,int d)
{
while(x<=n)
{
a[x][0]+=k;
a[x][1]+=d;
k+=d*lowbit(x);
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0,pos=x;
while(pos)
{
ans+=a[pos][0]+(x-pos)*a[pos][1];
pos-=lowbit(pos);
}
return ans;
}
int main()
{
int x,i,l,r,k,d,s,m;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
for(i=1;i<=m;i++)
{
scanf("%d",&s);
if(s==1)
{
scanf("%d%d%d%d",&l,&r,&k,&d);
add(l,k,d);
add(r+1,-k-(r-l+1)*d,-d);
}
else
{
scanf("%d",&x);
printf("%d\n",p[x]+sum(x));
}
}
return 0;
}