您的位置:首页 > 其它

POJ3468(线段树成段增加)

2016-07-23 19:50 337 查看
题目链接

大牛博客链接

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100000+5;
typedef long long ll;
struct tree
{
ll l,r,sum,inc;
}a[maxn*4];
ll c[maxn];

void build(ll o,ll l,ll r)   //初始建树
{
a[o].l=l,a[o].r=r,a[o].inc=0;
if(l==r)
{
a[o].sum=c[l];
return;
}
else
{
ll m=(l+r)/2;
build(o*2,l,m);
build(o*2+1,m+1,r);
a[o].sum=a[o*2].sum+a[o*2+1].sum;
return;
}
}

void add(ll o,ll p,ll q,ll v)   //对区间[p,q] 上的每个点增加v
{
if(a[o].l==p&&a[o].r==q)
{
a[o].inc+=v;
return;
}
a[o].sum+=v*(q-p+1);
ll m=(a[o].l+a[o].r)/2;
if(q<=m) add(o*2,p,q,v);
else if(p>m) add(o*2+1,p,q,v);
else
{
add(o*2,p,m,v);
add(o*2+1,m+1,q,v);
}
return;
}

ll query(ll o,ll p,ll q)     //查询区间[p,q]的和
{
if(a[o].l==p&&a[o].r==q)
{
return a[o].sum+(q-p+1)*a[o].inc;
}

a[o].sum+=(a[o].r-a[o].l+1)*a[o].inc;     //将标记向下推
int m=(a[o].l+a[o].r)/2;
add(o*2,a[o].l,m,a[o].inc);
add(o*2+1,m+1,a[o].r,a[o].inc);
a[o].inc=0;

if(q<=m) return query(o*2,p,q);
else if(p>m) return query(o*2+1,p,q);
else return query(o*2,p,m)+query(o*2+1,m+1,q);
}

int main()
{
ll n,q;
scanf("%I64d%I64d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%I64d",&c[i]);
build(1,1,n);
char ch;
for(int i=1;i<=q;i++)
{
cin >> ch;
if(ch=='Q')
{
ll p,q;
scanf("%I64d%I64d",&p,&q);
printf("%I64d\n",query(1,p,q));
}
else if(ch=='C')
{
ll a,b,v;
scanf("%I64d%I64d%I64d",&a,&b,&v);
add(1,a,b,v);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: