A Simple Problem with Integers-POJ3468 区间修改+区间查询
题意:
给你n个数和2个操作,C操作是将一个区间内的每个数都加上k,Q操作是询问一个区间的和
链接:http://poj.org/problem?id=3468
思路:
线段树区间修改+区间查询
代码:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <math.h> using namespace std; const int MAXN=2e5+5; typedef long long ll; ll tree[MAXN<<2]; ll lazy[MAXN<<2]; //lazy数组为区间修改时引进的一个标记数组 void push_up(ll node) { tree[node]=tree[node<<1]+tree[node<<1|1]; } void build(ll node,ll l, ll r) { if(l==r) { scanf("%lld",&tree[node]); return ; } ll mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1|1,mid+1,r); push_up(node); } /* push_down函数用来下传lazy标记,左右儿子的lazy等于父亲节点的lazy, 左儿子的区间和改变的数值为左儿子的区间长度*lazy[node]的值,右儿子同理, 下传结束后将父亲节点的lazy[node]变为0. */ void push_down(int node,int l,int r,int mid) { lazy[node<<1]+=lazy[node]; lazy[node<<1|1]+=lazy[node]; tree[node<<1]+=(mid-l+1)*lazy[node]; tree[node<<1|1]+=(r-mid)*lazy[node]; lazy[node]=0; } void update(int node,int l,int r,int x,int y,int k) //区间修改函数 { if(x<=l&&y>=r) //如果l,r在范围内,该区间的和直接增加(r-l+1)*k,打上lazy标记 { tree[node]+=(r-l+1)*k; lazy[node]+=k; return; } ll mid=(l+r)>>1; if(lazy[node]) //如果有lazy标记,则下传 push_down(node,l,r,mid); if(x<=mid) update(node<<1,l,mid,x,y,k); if(y>mid) update(node<<1|1,mid+1,r,x,y,k); push_up(node); //修改他父亲区间的和 } ll query(ll node,ll l,ll r,ll x,ll y) { if(x<=l&&y>=r) return tree[node]; ll mid=(l+r)>>1; if(lazy[node])push_down(node,l,r,mid); ll ans=0; if(x<=mid) ans+=query(node<<1,l,mid,x,y); if(y>mid) ans+=query(node<<1|1,mid+1,r,x,y); return ans; } int main() { ll n,q;scanf("%lld%lld",&n,&q); build(1,1,n); for(int i=1;i<=q;i++) { char str[3]; scanf("%s",str); ll x,y; if(str[0]=='Q') { scanf("%lld%lld",&x,&y); printf("%lld\n",query(1,1,n,x,y)); } else { ll k; scanf("%lld%lld%lld",&x,&y,&k); update(1,1,n,x,y,k); } } return 0; }