题目描述 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
这个是树状数组的比较复杂的操作了,我比较懒,有人写的比较好,我就不想写了,直接安利:http://blog.csdn.net/fsahfgsadhsakndas/article/details/52650026
然后没有什么好说的了,直接放代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x) memset(x,0,sizeof(x))
#define clrmax(x) memset(x,127,sizeof(x))
#define M 200005
#define lowbit(x) (x&(-x))
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
using namespace std;
ll tree[M],tree2[M],n,m;
void add(ll *a,ll x,ll y)
{
for(int i=x;i<=M;i+=lowbit(i))
a[i]+=y;
}
ll find(ll *a,ll x)
{
ll ret=0;
for(int i=x;i;i-=lowbit(i))
ret+=a[i];
return ret;
}
ll sigema(int x)
{
ll ret=0;
ret+=x*find(tree,x)-find(tree2,x);
return ret;
}
int main()
{
freopen("in.txt","r",stdin);
scanf(LL,&n);
int last=0;
for(int i=1;i<=n;i++)
{
ll x;
scanf(LL,&x);
add(tree,i,x-last);
add(tree2,i,(i-1)*(x-last));
last=x;
}
scanf(LL,&m);
while(m--)
{
int a;
scanf(LL,&a);
if(a==1)
{
ll b,c,x;
scanf(LL LL LL,&b,&c,&x);
add(tree,b,x);
add(tree,c+1,-x);
add(tree2,b,x*(b-1));
add(tree2,c+1,-x*(c));
}
else
{
ll b,c;
scanf(LL LL,&b,&c);
printf(LL"\n",sigema(c)-sigema(b-1));
}
}
return 0;
}
大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。