线段树单点更新+区间更新+离散化

来源:互联网 发布:哈尔滨学院教务网络管 编辑:程序博客网 时间: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
原创粉丝点击