题目链接:http://codevs.cn/problem/1082/
题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
1
2
3
2
1 2 3 2
2 2 3
样例输出 Sample Output
9
数据范围及提示 Data Size & Hint
数据范围
1<=n<=200000
1<=q<=200000
分析:
套公式,需要开二维的数组
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 200002
using namespace std;
ll c[205000][2],num[200500];
ll lowbit(ll x)
{
return x&(-x);
}
void update(ll x,ll val,ll p)
{
while(x<maxn)
{
c[x][p]+=val;
x+=lowbit(x);
}
}
ll query(ll x,ll p)
{
ll sum=0;
while(x>0)
{
sum+=c[x][p];
x-=lowbit(x);
}
return sum;
}
ll solve(ll y)
{
ll ans;
ans=(y+1)*(query(y,0))-query(y,1);
return ans;
}
int main()
{
ll n,i,j,x,y,val,t,ans,op,q;
ans=1;
scanf("%lld",&n);
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
scanf("%lld",&num[i]);
update(i,num[i]-num[i-1],0);
update(i,i*(num[i]-num[i-1]),1);
}
scanf("%lld",&q);
while(q--)
{
scanf("%lld",&op);
if(op==1)
{
scanf("%lld%lld%lld",&x,&y,&val);///区间更新
update(x,val,0);
update(y+1,-val,0);
update(x,val*x,1);
update(y+1,-val*(y+1),1);
}
else
{
scanf("%lld%lld",&x,&y);///区间查询
printf("%lld\n",(solve(y)-solve(x-1)));
}
}
}