线段树单点更新+区间更新+离散化
来源:互联网 发布:哈尔滨学院教务网络管 编辑:程序博客网 时间:2024/05/29 06:46
线段树单点更新
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 0xffffff0using 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 intusing 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; }
0 0
- 线段树单点更新+区间更新+离散化
- poj2528 离散化+线段树区间更新
- POJ2528 线段树 区间更新 离散化
- hdoj 4325 Flowers 【线段树 + 离散化】【区间更新 单点查询】
- HDOJ 4325 Flowers 【线段树 离散化 区间更新 单点查询】
- hdu4288 Coder 离线线段树 单点更新 区间求和 离散化?
- POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)
- 线段树(单点更新+区间更新)
- POJ 2528 区间端点离散化,线段树区间更新
- 线段树 --- 单点更新、求逆序对、离散化
- HDU 4267 线段树 离散点区间更新, 自叶子节点至根单点查询
- zoj (单点更新区间查询:线段树)
- 线段树求区间和(单点更新)
- 线段树单点更新和区间查询
- 线段树(单点更新,区间求和)
- hdu1166(线段树单点更新区间查询)
- poj2352Stars【线段树单点更新区间求和】
- 线段树 单点更新求区间和
- Windows网络编程基础学习
- hibernate异常"Found shared references to a collection
- jqgrid中cell的特殊处理
- 【IT公司笔试面试】75道逻辑推理题及答案
- build Intent
- 线段树单点更新+区间更新+离散化
- make到cmake简介
- hdu1106-排序
- Jmeter基础之---jmeter基础概念
- win遍历所有硬件
- 利用指针排序
- 对 Linux 新手非常有用的 20 个命令
- undefined与null的区别
- GSC3280开发板