其实这几道题都比较裸的,不过粘一下代码,送给像我一样的初学者,希望有所帮助:
题目:http://codevs.cn/problem/1082/
区间修改,区间查询
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 4e5 + 5;
struct zt
{
ll l,r,sum,jia,sz;
zt *lift,*right;
};
zt tree[MAXN];
ll n,q,a,b,c,cnt = 0;
void build(zt *root,ll l,ll r)
{
root->l = l;root->r = r;root->sum = 0;root->jia = 0;root->sz = r - l + 1;
if(l == r)
return;
int mid = (l + r)>>1;
root->lift = &tree[++cnt];
root->right = &tree[++cnt];
build(root->lift,l,mid);
build(root->right,mid + 1,r);
}
void add(zt *root,ll l,ll r,ll ql,ll qr,ll x)
{
root->sum += x * (min(qr,r) - max(ql,l) + 1);
if(l >= ql&&qr >= r)
{
root->jia += x;
return;
}
int mid = (l + r)>>1;
if(ql <= mid)
add(root->lift,l,mid,ql,qr,x);
if(qr > mid)
add(root->right,mid + 1,r,ql,qr,x);
}
ll query(zt *root,ll l,ll r,ll ql,ll qr)
{
if(l >= ql&&qr >= r)
return root->sum;
if(root->jia)
{
root->right->jia += root->jia;
root->right->sum += (root->jia)*(root->right->sz);
root->lift->jia += root->jia;
root->lift->sum += (root->jia)*(root->lift->sz);
root->jia = 0;
}
int mid = (l + r)>>1;
if(qr <= mid)
return query(root->lift,l,mid,ql,qr);
if(ql > mid)
return query(root->right,mid + 1,r,ql,qr);
return (query(root->lift,l,mid,ql,qr) + query(root->right,mid + 1,r,ql,qr));
}
int main()
{
scanf("%lld",&n);
build(tree,1,n);
for(int i = 1;i <= n;i ++)
{
scanf("%lld",&a);
add(tree,1,n,i,i,a);
}
scanf("%lld",&q);
for(int i = 1;i <= q;i ++)
{
scanf("%lld",&a);
if(a == 1)
{
scanf("%lld %lld %lld",&a,&b,&c);
add(tree,1,n,a,b,c);
}
else
{
scanf("%lld %lld",&a,&b);
cout<<query(tree,1,n,a,b)<<'\n';
}
}
}