线段树单点更新
http://poj.org/problem?id=3264
题意:
给定Q(1 ≤ Q≤ 200,000)个数A1,A2… AQ,,多次求任一区间Ai–Aj中最大数和最小数的差。
#include<stdio.h>
#include<algorithm>
#define MAX 200009
#define INF 0xffffff0
using namespace std;
int num[MAX],minV,maxV;
struct Node{
int minV;
int maxV;
int L;
int R;
int mid(){
return (L+R)/2;
}
}tree[MAX*4];
void build(int root, int s,int e){
tree[root].L=s;
tree[root].R=e;
tree[root].minV=INF;
tree[root].maxV=-INF;
if(tree[root].L!=tree[root].R){
build(root*2,s,tree[root].mid());
build(root*2+1,tree[root].mid()+1,e);
}
}
void insert(int root, int pos, int val){
if(tree[root].L==tree[root].R){
tree[root].minV=tree[root].maxV=val;
return;
}
tree[root].minV=min(tree[root].minV,val);
tree[root].maxV=max(tree[root].maxV,val);
if(pos<=tree[root].mid()){
insert(root*2, pos, val);
}else{
insert(root*2+1,pos,val);
}
}
void query(int root, int s, int e){
if(tree[root].minV>=minV&&tree[root].maxV<=maxV){
return;
}
if(tree[root].L==s&&tree[root].R==e){
minV=min(tree[root].minV,minV);
maxV=max(tree[root].maxV,maxV);
return ;
}
if(e<=tree[root].mid()){
query(root*2,s,e);
}else if(s>tree[root].mid()){
query(root*2+1,s,e);
}else{
query(root*2,s,tree[root].mid());
query(root*2+1,tree[root].mid()+1,e);
}
}
int main(){
int N,Q;
while(~scanf("%d %d",&N,&Q)){
build(1,1,N);
for(int i=1;i<=N;i++){
scanf("%d",&num[i]);
insert(1,i,num[i]);
}
int st,ed;
for(int i=1;i<=Q;i++){
scanf("%d %d",&st,&ed);
minV=INF;
maxV=-INF;
query(1,st,ed);
printf("%d\n",maxV-minV);
}
}
return 0;
}
线段树区间更新:
http://poj.org/problem?id=3468
题意:
给定Q(1 ≤ Q≤ 100,000)个数A1,A2… AQ,,以及可能多次进行的两个操作:
1)对某个区间Ai … Aj的每个数都加n(n可变)2) 求某个区间Ai … Aj的数的和
#include<stdio.h>
#include<algorithm>
#define MAX 200009
#define INF 0xffffff0
#define LL long long int
using namespace std;
LL num[MAX],cnt=0;
struct Node{
LL L;
LL R;
Node *pL;
Node *pR;
LL sum;
LL add;
}tree[MAX];
LL mid(struct Node *root){
return (root->L+root->R)/2;
}
void build(struct Node *root,int L,int R){
root->L=L;
root->R=R;
root->sum=0;
root->add=0;
if(L==R) return;
LL midd=(L+R)/2;
cnt++;
root->pL=tree+cnt;
build(root->pL,L,midd);
cnt++;
root->pR=tree+cnt;
build(root->pR,midd+1,R);
}
void insert(struct Node *root, int pos, int val){
if(root->L==root->R){
root->sum=val;
return;
}
root->sum+=val;
LL midd=mid(root);
if(pos<=midd)insert(root->pL, pos, val);
else insert(root->pR, pos, val);
}
void add(struct Node *root, LL L, LL R, LL val){
if(root->L==L&&root->R==R){
root->add+=val;
return;
}
root->sum+=(R-L+1)*val;
LL midd=mid(root);
if(R<=midd)add(root->pL, L, R, val);
else if(L>midd) add(root->pR, L, R, val);
else {
add(root->pL, L, mid(root), val);
add(root->pR, mid(root)+1, R,val);
}
}
LL query(struct Node *root, LL L, LL R){
if(root->L==L&&root->R==R){
return root->sum+(R-L+1)*root->add;
}
LL midd=mid(root);
root->sum+=(root->R-root->L+1)*root->add;
add(root->pL, root->L, midd, root->add);
add(root->pR, midd+1, root->R, root->add);
root->add=0;
if(R<=midd) return query(root->pL, L, R);
else if(L>midd) return query(root->pR, L, R);
else return query(root->pL, L, midd)+query(root->pR, midd+1, R);
}
int main(){
LL N,Q;
while(~scanf("%I64d %I64d",&N,&Q)){
cnt=0;
build(tree,1,N);
for(int i=1;i<=N;i++){
scanf("%I64d",&num[i]);
insert(tree,i,num[i]);
}
char str[10];
for(int i=1;i<=Q;i++){
scanf("%s",str);
if(str[0]=='Q'){
LL a,b;
scanf("%I64d %I64d",&a,&b);
LL ans=query(tree,a,b);
printf("%I64d\n",ans);
}else{
LL a,b,c;
scanf("%I64d %I64d %I64d",&a,&b,&c);
add(tree,a,b,c);
}
}
}
return 0;
}
这题这样写的效率更高些:
#include <cstdio>
#define LL __int64
const int N = 500010;
LL num[N], t;
struct node{
int left, right;
LL sum, add;
}arr[N];
void pushDown(int idx){
LL tmp = arr[idx].add;
int l = idx << 1, r = (idx << 1) ^ 1;
arr[l].add += tmp;
arr[l].sum += (arr[l].right - arr[l].left + 1) * tmp;
arr[r].add += tmp;
arr[r].sum += (arr[r].right - arr[r].left + 1) * tmp;
arr[idx].add = 0;
}
void build(int idx, int l, int r){
arr[idx].left = l, arr[idx].right = r;
arr[idx].add = 0;
if(l == r){
arr[idx].sum = num[l];
return ;
}
int mid = (l + r) >> 1;
build(idx * 2, l, mid);
build(idx * 2 + 1, mid + 1, r);
arr[idx].sum = arr[idx * 2].sum + arr[idx * 2 + 1].sum;
}
void update(int idx, int l, int r, int val){
if(arr[idx].right < l||arr[idx].left > r)
return ;
if(arr[idx].left >= l&&arr[idx].right <= r){
arr[idx].sum += (arr[idx].right - arr[idx].left + 1) * val;
arr[idx].add += val;
return ;
}
if(arr[idx].add != 0)
pushDown(idx);
update(idx * 2, l, r, val);
update(idx * 2 + 1, l, r, val);
arr[idx].sum = arr[idx * 2].sum + arr[idx * 2 + 1].sum;
}
LL query(int idx, int l, int r){
if(arr[idx].right < l||arr[idx].left > r)
return 0;
if(arr[idx].left >= l&&arr[idx].right <= r)
return arr[idx].sum;
if(arr[idx].add != 0)
pushDown(idx);
LL x = query(idx * 2, l, r);
LL y = query(idx * 2 + 1, l, r);
return x + y;
}
int main(){
int n, i, q, l, r;
char ord;
while(~scanf("%d%d", &n, &q)){
for(i = 1;i <= n;i++)
scanf("%lld", &num[i]);
build(1, 1, n);
while(q--){
scanf("\n%c", &ord);
if(ord == 'Q'){
scanf("%d%d", &l, &r);
printf("%lld\n", query(1, l, r));
} else {
scanf("%d%d%lld", &l, &r, &t);
update(1, l, r, t);
}
}
}
return 0;
}