例题: 敌兵布阵(改点求点)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int mod=1e9+10;
const int M=5e4 + 10;
ll a[M*4]={0};
ll tree[M*4]={0};
ll Add[M*4]={0};
void bulid(ll node, ll left, ll right)//建树
{
if(left == right){
tree[node] = a[left];
return ;
}
ll mid = (left + right) / 2;
bulid(node * 2, left, mid);
bulid(node * 2 + 1, mid +1, right);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
void PushDown(ll node, ll ln, ll rn)//左右子树叶节点的数量
{
if(Add[node]){
Add[node*2] += Add[node];
Add[node*2+1] += Add[node];
tree[node*2] += Add[node] * ln;
tree[node*2 + 1] += Add[node] * rn;
Add[node] = 0;
}
return ;
}
ll query(ll node, ll L, ll R, ll left, ll right)//区间查询
{
if(L <= left && right <= R)
return tree[node];
ll mid = (left + right)/2;
PushDown(node, mid- left + 1, right - mid);
ll ans = 0;
if(L <= mid )
ans = query(node * 2, L, R, left, mid);
if(R > mid)
ans += query(node * 2 + 1, L, R, mid+1, right);
return ans;
}/*
void update1(ll node, ll left, ll right, ll idx, ll val)//单点更新
{
if(left == right){
//a[idx] += val;
tree[node] += val;
return ;
}
ll mid = (left + right) / 2;
if(idx >= left && idx <=mid)
update1(node*2, left, mid, idx, val);
else
update1(node * 2 +1, mid + 1, right, idx, val);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}*/
//区间更新 L~R 加 P
void update2(ll node, ll left, ll right, ll L, ll R, ll p)
{
if(left >= L && right <= R){
tree[node] += p * (right - left +1);
Add[node] += p;
return ;
}
ll mid = (left + right)/2;
if(L <= mid)
update2(node*2, left, mid, L, R, p);
else
update2(node*2+1, mid+1, right, L, R, p);
}
int main()
{
ll n,i,j,T,aa,bb,e=1;
scanf("%lld",&T);
while(T--){
memset(Add,0,sizeof(Add));
memset(tree,0,sizeof(tree));
memset(a,0,sizeof(a));
scanf("%lld",&n);
for(int i=1; i<=n; i++)
scanf("%lld",&a[i]);
bulid(1, 1, n);
char s[10];
printf("Case %lld:\n",e++);
while(1){
//cin>>s;
scanf(" %s",s);
if(s[0] == 'E')
break;
scanf("%lld %lld",&aa, &bb);
if(s[0] == 'Q'){
ll ans = query(1, aa, bb, 1, n);
printf("%lld\n",ans);
}
else if(s[0] == 'A'){
update1(1, 1, n, aa, bb);
}
else if(s[0] == 'S'){
update1(1, 1, n, aa, -bb);
}
}
}
return 0;
}
//求区间最大值时更改tree就可以了,取子节点的最大值
Color the ball(该段求点)
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
const int MAX=100100;
int a[MAX];
int sum[4*MAX];
int add[4*MAX];
/*void Build(int l,int r,int n)//建立线段树
{
if(l==r)//到叶子结点赋值
{
sum[n]=a[l];
return ;
}
int m=(l+r)/2;
Build(l,m,2*n);//建立左子树
Build(m+1,r,2*n+1);//建立右子树
sum[n]=sum[2*n]+sum[2*n+1];
return ;
}*/
void PushDown(int n,int ln,int rn)//ln和rn是左子树和右子树树叶的数量
{
if(add[n])
{
add[n*2]+=add[n];
add[n*2+1]+=add[n];
sum[n*2]+=add[n]*ln;
sum[n*2+1]+=add[n]*rn;
add[n]=0;
}
return ;
}
void Update2(int L,int R,int c,int l,int r,int n)
{
if(l>=L&&R>=r)
{
sum[n]+=c*(r-l+1);
add[n]+=c;
return ;
}
int m=(l+r)/2;
PushDown(n,m-l+1,r-m);
if(L<=m)
Update2(L,R,c,l,m,n*2);
if(R>=m+1)
Update2(L,R,c,m+1,r,n*2+1);
sum[n]=sum[2*n]+sum[2*n+1];
return ;
}
/*
void Update(int l,int r,int sumn,int am,int p)//p是更改的值
{
//sumn是sum数组里面的,am是a数组里面的
//首先要找到需要更新的am的位置
int mid;
mid=(l+r)/2;
if(l==r)
{
sum[sumn]+=p;
return ;
}
if(mid>=am)
{
Update(l,mid,sumn*2,am,p);
}
else
{
Update(mid+1,r,sumn*2+1,am,p);
}
//在回来的路上顺便更新sum数组。
sum[sumn]=sum[sumn*2]+sum[sumn*2+1];
}*/
int Query(int L,int R,int l,int r,int p)//p是当前位置
{
if(L<=l&&r<=R)
return sum[p];
int m=(l+r)/2;
PushDown(p,m-l+1,r-m);
int ans=0;
if(L<=m)
ans+=Query(L,R,l,m,p*2);
if(R>m)
ans+=Query(L,R,m+1,r,p*2+1);
return ans;
}
int main()
{
int n,i;
while(cin>>n&&n)
{
memset(a,0,sizeof(a));
memset(sum,0,sizeof(sum));
memset(add,0,sizeof(add));
for(i=0;i<n;i++)
{
int x,y;
cin>>x>>y;
Update2(x,y,1,1,n,1);
}
for(i=1;i<=n;i++)
{
if(i==1)
cout<<Query(i,i,1,n,1);
else
cout<<" "<<Query(i,i,1,n,1);
}
cout<<endl;
}
return 0;
}