PKU 2750 Potted Flower 解题报告

来源:互联网 发布:apache ivy 编辑:程序博客网 时间:2024/05/22 00:18
  1. /*
  2.   Title: Potted Flower
  3.   Author: Jeff
  4.   Time:  2008/10/28
  5.   Complexity: O(nlog(n));
  6.   Result: 7884K 344MS/ AC
  7.   Reference: 
  8.         http://203.208.39.99/search?q=cache:bZTSBU3KVGUJ:hi.baidu.com/fandywang_jlu/blog/item/505b40f4c864bddff3d38574.html+poj+2750&hl=zh-CN&lr=lang_zh-CN|lang_zh-TW&newwindow=1&gl=cn&st_usg=ALhdy29PmISlzFU8Pg-GsftyKbxS8Nqc6A&strip=1
  9.   Description: 
  10.         给定一个环形序列,进行在线操作,每次修改一个元素,
  11.         输出环上的最大连续子列的和。
  12.   Tips:
  13.         线段树+DP 
  14.         出题者的简单解题报告:把环从一个地方,切断拉成一条直线,
  15.         用线段树记录当前区间的非空最大子列和当前区间的非空最小
  16.         子列。如果环上的数都是正整数,答案是:环上数的总和-根
  17.         结点的非空最小子列;否则,答案是:max{根结点的非空最大
  18.         子列, 环上数的总和-根结点的非空最小子列},每次问答的
  19.         复杂度是O(logN)。
  20.   p.s. 
  21.   
  22. */

  23. #include <cstdio>
  24. #include <cstring>
  25. using namespace std;
  26. const int MAX = 100000;
  27. struct Node{
  28.     int sum;    //该区间数的总和 
  29.     int maxSum, minSum; //该区间 最大子列和 与 最小子列和 
  30.     int maxl, maxr; //该区间 从左端点开始的最大子列和 与 到右端点结束的最小子列和 
  31.     int minl, minr; //该区间 从左端点开始的最小子列和 与 到右端点结束的最小子列和 
  32. };
  33. int Num[MAX];
  34. Node M[1 << 18];

  35. inline int min(int a, int b){
  36.     return a < b ? a : b; 
  37. }
  38. inline int max(int a, int b){
  39.     return a > b ? a : b;    
  40. }

  41. //根据左右子节点更新父亲节点 (DP)
  42. void update_node(int parent, int left, int right){
  43.     M[parent].sum = M[left].sum + M[right].sum;
  44.     M[parent].maxSum = max(max(M[left].maxSum, M[right].maxSum), 
  45.                 M[left].maxr + M[right].maxl);
  46.     M[parent].minSum = min(min(M[left].minSum, M[right].minSum),
  47.                 M[left].minr + M[right].minl);
  48.     M[parent].maxl = max(M[left].maxl, M[left].sum+M[right].maxl);
  49.     M[parent].maxr = max(M[left].maxr+M[right].sum, M[right].maxr);
  50.     M[parent].minl = min(M[left].minl, M[left].sum+M[right].minl);
  51.     M[parent].minr = min(M[left].minr+M[right].sum, M[right].minr);
  52. }
  53. //初始化线段树 
  54. void init_tree(int node, int l, int r){
  55.     if(l == r){
  56.         M[node].sum = M[node].maxSum = M[node].minSum = Num[l];    
  57.         M[node].maxl = M[node].maxr = M[node].minl = M[node].minr = Num[l];
  58.     }else{
  59.         init_tree(node * 2, l, (l+r)/2);
  60.         init_tree(node*2+1, (l+r)/2+1, r);
  61.         update_node(node, node * 2, node * 2 + 1);    
  62.     }
  63.     //printf("(%d %d): %d %d %d/n", l, r, M[node].sum, M[node].maxSum, M[node].minSum);
  64. }

  65. //改变一个叶子节点的值,从叶子到树根更新各个节点值 log(n)
  66. void change_query(int node, int l, int r, int pos, int value){
  67.     //if(l <= pos <= r){
  68.         if(l == r){
  69.             if(l == pos)
  70.                 M[node].sum = M[node].maxSum = M[node].minSum = value;
  71.                 M[node].maxl = M[node].maxr = M[node].minl = M[node].minr = value;    
  72.         }else{
  73.             if(l <= pos && pos <= (l+r)/2)
  74.                 change_query(node * 2, l, (l+r)/2, pos, value);
  75.             else 
  76.                 change_query(node*2+1, (l+r)/2+1, r, pos, value);
  77.             update_node(node, node*2, node*2+1);
  78.         }
  79.     //}
  80.     //printf("(%d %d): %d %d %d/n", l, r, M[node].sum, M[node].maxSum, M[node].minSum);    
  81. }

  82. int main(){
  83.     freopen("in.txt""r", stdin);
  84.     freopen("out.txt""w", stdout);
  85.     int N;
  86.     while(scanf("%d", &N) != EOF){
  87.         for(int i = 0; i < N; i++)
  88.             scanf("%d", &Num[i]);
  89.         init_tree(1, 0, N-1);
  90.         int K, A, B;
  91.         scanf("%d", &K);
  92.         for(int i = 0; i < K; i++){
  93.             scanf("%d%d", &A, &B);
  94.             change_query(1, 0, N-1, A-1, B);
  95.             //printf("%d %d %d ", M[1].sum, M[1].maxSum, M[1].minSum);
  96.             if(M[1].sum == M[1].maxSum)printf("%d/n", M[1].sum - M[1].minSum);
  97.             else printf("%d/n", max(M[1].maxSum, M[1].sum - M[1].minSum));
  98.         }
  99.     }
  100.     return 0;    
  101. }
 
原创粉丝点击