题目链接:Click here~~
题意:
给你n个数,然后有两种操作,求某段区间的和 or 将某段区间元素加若干值。
解题思路:
线段树。。。模仿别人的。1516MS。
貌似zkw式线段树1329MS,两个树状数组可以做到1047MS,等以后再学,TAT。
#include <stdio.h>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)
typedef __int64 LL;
const int M = 100003;
int v[M];
struct Tnode
{
int l,r;
LL sum,delta; //sum记录区间和、delta记录区间的公共增量
}T[M<<2];
void Build(int u,int l,int r)
{
T[u].l = l , T[u].r = r;
if(l == r-1)
{
T[u].sum = v[l];
T[u].delta = 0;
return ;
}
int mid = MID(l,r);
Build(L(u),l,mid);
Build(R(u),mid,r);
T[u].sum = T[L(u)].sum + T[R(u)].sum;
T[u].delta = 0;
}
void Updata(int u,int l,int r,LL up)
{
if(T[u].l == l && T[u].r == r)
{
T[u].delta += up;
return ;
}
else
T[u].sum += up*(r-l);
int mid = MID(T[u].l,T[u].r);
if(l >= mid)
Updata(R(u),l,r,up);
else
if(r <= mid)
Updata(L(u),l,r,up);
else
{
Updata(L(u),l,mid,up);
Updata(R(u),mid,r,up);
}
}
LL Query(int u,int l,int r)
{
LL delta = T[u].delta;
if(T[u].l == l && T[u].r == r)
return T[u].sum + delta*(r-l);
T[L(u)].delta += delta;
T[R(u)].delta += delta;
T[u].sum += delta*(T[u].r-T[u].l);
T[u].delta = 0;
int mid = MID(T[u].l,T[u].r);
if(l >= mid)
return Query(R(u),l,r);
else
if(r <= mid)
return Query(L(u),l,r);
else
return Query(L(u),l,mid) + Query(R(u),mid,r);
}
int main()
{
int n,Q,a,b,t;
char cmd[2];
while(~scanf("%d%d",&n,&Q))
{
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
Build(1,1,n+1);
while(Q--)
{
scanf("%s%d%d",cmd,&a,&b);
if(cmd[0] == 'Q')
printf("%I64d\n",Query(1,a,b+1));
else
{
scanf("%d",&t);
Updata(1,a,b+1,t);
}
}
}
return 0;
}