zoukankan      html  css  js  c++  java
  • 线段树总结

    模板:

    点修改:

     1 int sum[maxn<<2], maxv[maxn<<2], minv[maxn<<2];  
     2   
     3 void maintain(int u)  
     4 {  
     5     int lc = u*2, rc = u*2+1;  
     6     sum[u] = sum[lc] + sum[rc];  
     7     maxv[u] = max(maxv[lc], maxv[rc]);  
     8     minv[u] = min(minv[lc]. minv[rc]);  
     9 }  
    10   
    11 void build(int u, int l, int r)  
    12 {  
    13     if(l==r)  
    14     {  
    15         sum[u] = maxv[u] = minv[u] = 0;  
    16         return;  
    17     }  
    18       
    19     int mid = (l+r)>>1;  
    20     build(u*2, l, mid);  
    21     build(u*2+1, mid+1, r);  
    22     maintain(u);  
    23 }  
    24   
    25 void add_val(int u,int l,int r,int x, int val)  
    26 {  
    27     if(l==r)  
    28     {  
    29         sum[u] += val;  
    30         maxv[u] += val;  
    31         minv[u] += val;  
    32         return ;  
    33     }  
    34       
    35     int mid = (l+r)>>1;  
    36     if(x<=mid) add_val(u*2, l, mid, x, val);  
    37     else add_val(u*2+1, mid+1, r, x, val);  
    38     maintain(u);  
    39 }  
    40   
    41 void set_val(int u, int l, int r, int x, int val)  
    42 {  
    43     if(l==r)  
    44     {  
    45         sum[u] = val;  
    46         maxv[u] = val;  
    47         minv[u] = val;  
    48         return;  
    49     }  
    50       
    51     int mid = (l+r)>>1;  
    52     if(x<=mid) set_val(u*2, l, mid, x, val);  
    53     else set_val(u*2+1, mid+1, r, x, val);  
    54     maintain(u);  
    55 }  
    56   
    57 int maxx, minn;   
    58 int query(int u,int l, int r, int x, int y)  
    59 {  
    60     if(x<=l && r<=y)  
    61     {  
    62         maxx = max(maxx, maxv[u]);  
    63         minn = min(minn, minv[u]);  
    64         return sum[u];  
    65     }  
    66       
    67     int ret = 0;  
    68     int mid = (l+r)>>1;  
    69     if(x<=mid) ret += query(u*2, l, mid, x, y);  
    70     if(y>=mid+1) ret += query(u*2+1, mid+1, r, x ,y);  
    71     return ret;  
    72 }  
    View Code

    区间修改:

      1 int sum[maxn<<2], maxv[maxn<<2], minv[maxn<<2], addv[maxn<<2], setv[maxn<<2];  
      2   
      3 void pushup(int u)  
      4 {  
      5     int l = 2*u, r = 2*u+1;  
      6     sum[u] = sum[l] + sum[r];  
      7     maxv[u] = max(maxv[l], maxv[r]);  
      8     minv[u] = min(minv[l], minv[r]);  
      9 }  
     10   
     11 void pushdown(int u, int len)  
     12 {  
     13     int lc = 2*u, rc = 2*u+1;  
     14     if(setv[u]>=0)  
     15     {  
     16         addv[lc] = addv[rc] = 0;  
     17         minv[lc] = minv[rc] = maxv[lc] = maxv[rc] = setv[u];  
     18         sum[lc] = (len+1)/2*setv[u];  
     19         sum[rc] = len/2*setv[u];  
     20         setv[lc] = setv[rc] = setv[u];  
     21         setv[u] = -1;  
     22     }  
     23   
     24     if(addv[u])  
     25     {  
     26         sum[lc] += (len+1)/2*addv[u];  
     27         sum[rc] += len/2*addv[u];  
     28         maxv[lc] += addv[u]; minv[lc] += addv[u];  
     29         maxv[rc] += addv[u]; minv[rc] += addv[u];  
     30         addv[lc] += addv[u]; addv[rc] += addv[u];  
     31         addv[u] = 0;  
     32     }  
     33 }  
     34   
     35 void build(int u, int l, int r)  
     36 {  
     37     if(l==r)  
     38     {  
     39         sum[u] = maxv[u] = minv[u] = 0;  
     40         return;  
     41     }  
     42   
     43     int mid = (l+r)>>1;  
     44     build(u*2, l, mid);  
     45     build(u*2+1, mid+1, r);  
     46     pushup(u);  
     47 }  
     48   
     49 void set_val(int u, int l, int r, int x, int y, int val)  
     50 {  
     51     if(x<=l && r<=y)  
     52     {  
     53         addv[u] = 0;  
     54         maxv[u] = minv[u] = val;  
     55         sum[u] = (r-l+1)*val;  
     56         setv[u] = val;  
     57         return;  
     58     }  
     59   
     60     pushdown(u, r-l+1);  
     61     int mid = (l+r)>>1;  
     62     if(x<=mid) set_val(u*2, l, mid, x, y, val);  
     63     if(y>=mid+1) set_val(u*2+1, mid+1, r, x, y, val);  
     64     pushup(u);  
     65 }  
     66   
     67   
     68 void add_val(int u, int l, int r, int x, int y, int val)  
     69 {  
     70     if(x<=l && r<=y)  
     71     {  
     72         maxv[u] += val;  
     73         minv[u] += val;  
     74         sum[u] += (r-l+1)*val;  
     75         addv[u] += val;  
     76         return;  
     77     }  
     78   
     79     pushdown(u, r-l+1);  
     80     int mid = (l+r)>>1;  
     81     if(x<=mid)  add_val(u*2, l, mid, x, y, val);  
     82     if(y>=mid+1) add_val(u*2+1, mid+1, r, x, y, val);  
     83     pushup(u);  
     84 }  
     85   
     86 int ansmax, ansmin;  
     87 int query(int u, int l, int r, int x, int y)  
     88 {  
     89     if(x<=l && r<=y)  
     90     {  
     91         ansmax = max(ansmax, maxv[u]);  
     92         ansmin = min(ansmin, minv[u]);  
     93         return sum[u];  
     94     }  
     95   
     96     pushdown(u, r-l+1);  
     97     int mid = (l+r)>>1;  
     98     int ret = 0;  
     99     if(x<=mid) ret += query(u*2, l, mid, x, y);  
    100     if(y>=mid+1) ret += query(u*2+1, mid+1, r, x, y);  
    101     return ret;  
    102 }  
    View Code

    一、点修改:

    HDU1166 敌兵布阵

    HDU1754 —— I Hate It

    POJ3264 Balanced Lineup 

    二、区间修改:

    HDU3974 Assign the task 

    POJ3468 A Simple Problem with Integers

    HDU4027 Can you answer these queries?(区间开根)

    CodeChef - ANDMIN (区间与&)

    三、区间染色:

    HDU1698 Just a Hook

    ZOJ1610 Count the Colors 

    POJ2528 Mayor's posters

    四、区间合并:

    HDU1540 Tunnel Warfare 

    SPOJ - GSS1 (区间最大连续和)

    五、连续型线段树(求面积、周长、体积):

    1.此种线段树的操作对象为连续型,即最小的元素为长度为1的区间[l,r],其中l和r只代表端点(r-l>=1),用于确定区间的位置和长度,在l处和r处没有特别的含义。而以往做的什么单点更新以及普通的区间更新之类的,都属于离散型,他们的最小的操作对象是一个一个的点,因而在l处和r处是有含义的。

    2.因为最小的操作对象为一段区间,因而线段树的写法也需要做适当变形:

    void push_up(int u, int l, int r)
    {
        if(times[u]>0)      //该区间被覆盖: 覆盖长度为区间长度
            sum[u] = X[r] - X[l];
        else            //该区间没有被覆盖: 如果为单位区间,则覆盖长度为0,否则为两个子区间的覆盖长度之和。
            sum[u] = (l+1==r)?0:sum[u*2]+sum[u*2+1];
    }
    
    void add(int u, int l, int r, int x, int y, int v)
    {
        if(x<=l && r<=y)
        {
            times[u] += v;
            push_up(u, l, r);
            return;
        }
    
        int mid = (l+r)>>1;
        if(x<=mid-1) add(u*2, l, mid, x, y, v);  //在左端至少要有一个单位区间(为[mid-1, mid],所以x需要满足x<=mid-1)
        if(y>=mid+1) add(u*2+1, mid, r, x, y, v); //在右端至少要有一个单位区间(为[mid, mid+1],所以y需要满足y>=mid+1)
        push_up(u, l, r); 
    }
    View Code

    3.为何不需要push_down()和query()函数呢?

    答:因为push_down()的本质作用是把修改传递下去,以查询更小的区间的具体信息。但是对于此种类型的线段树,我们只需要获取整段的信息(即sum[1]),而不需要取查询子区间的信息,所有:当修改了某一子区间的后,只需把修改信息往上更新,而不需要理会往下的更小的子区间。因而不需要push_down()和query()函数。

    HDU1542 Atlantis (矩形并面积)

    HDU1255 覆盖的面积 (矩形交面积)

    POJ1177 Picture (矩形并周长)

    HDU3642 Get The Treasury  (长方体交体积)

  • 相关阅读:
    制作 MarkText 的导航栏和动画背景
    某雅互动静态页面
    html5 拖拽及用 js 实现拖拽
    九宫格
    phaser3 入门实例——收集星星游戏
    Flexbox Froggy:练习 Flex 布局的小游戏
    JS30
    ElasticSearch
    JVM
    jstack命令的使用
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7750479.html
Copyright © 2011-2022 走看看