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

    今天写了线段树,

    把以前不会的补了回来,

    现在OK了,

    一会附上线段树大模板,

    各种操作都全了,

    先简介一下,

    总结出了几个道理:

    1 区间加,区间替换的lazy下放不一样,

    区间加对于tree[ i ]中的全部元素都 +=

    区间替换就是直接赋值

    2:lazy的含义是对于一个区间,这个区间完成一个操作,而该区间子区间没有进行该操作,

    子区间所有元素 (包括最大值,最小值),都要加入lazy标记,

    OK啦

    下面是三个模板,最全啦,

    操作格子1,是单点替换,区间查询区间和,最大值,最小值,

    操作格子2,加上了区间替换为一个数,

    操作格子3,加上了区间加一个数,

    话不多说,

    上代码, ( 代码里有注释,但不能直接提交,要弄明白 )

    ps : 305行大代码,累死了

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <bits/stdc++.h>
      4 using namespace std;
      5 typedef long long ll;
      6 typedef unsigned long long ull;
      7 
      8 #define ls (t<<1)
      9 #define rs ((t<<1)|1)
     10 
     11 
     12 #define mk make_pair
     13 #define pb push_back
     14 #define fi first
     15 #define se second
     16 
     17 #define MAXN 500001
     18 
     19 struct tree{
     20     int l,r;
     21     ll sum,add,minn,maxx;
     22     //可以统计 区间和,区间加,区间最大/小
     23     #define l(x) t[x].l
     24     #define r(x) t[x].r
     25     #define sum(x) t[x].sum
     26     #define add(x) t[x].add
     27     #define maxx(x) t[x].maxx
     28     #define minn(x) t[x].minn
     29     tree() {
     30         l=r=0;
     31         sum=add=minn=maxx=0;
     32     }
     33 }t[MAXN*4];
     34 
     35 int a[MAXN];
     36 
     37 void build(int p,int l,int r) {
     38     l(p)=l;
     39     r(p)=r;
     40     add(p)=0;
     41     if (l==r) {
     42         sum(p)=a[l];
     43         maxx(p)=a[l];
     44         minn(p)=a[l];
     45         return;
     46     }
     47     int mid=(l+r)/2;
     48     build(p*2,l,mid);
     49     build(p*2+1,mid+1,r);
     50     sum(p)=sum(p*2)+sum(p*2+1);
     51     maxx(p)=max(maxx(p*2),maxx(p*2+1));
     52     minn(p)=min(minn(p*2),minn(p*2+1));
     53 }
     54 
     55 void spread1(int p) {
     56     //lazy标记下放与清除 
     57     //这里lazy用于区间加一个数 
     58     if (add(p)) {
     59         sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1);
     60         maxx(p*2)+=add(p);
     61         minn(p*2)+=add(p);
     62         //更新左节点 
     63         sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1);
     64         maxx(p*2+1)+=add(p);
     65         minn(p*2+1)+=add(p);
     66         //更新右节点 
     67         add(p*2)+=add(p);
     68         //左节点下放lazy 
     69         add(p*2+1)+=add(p);
     70         //右节点下放lazy 
     71         add(p)=0;
     72         //lazy清空 
     73     }
     74 }
     75 void spread2(int p) {
     76     //lazy标记下放与清除 
     77     //这里lazy用于区间替换为一个数 
     78     if (add(p)) {
     79         sum(p*2)=add(p)*(r(p*2)-l(p*2)+1);
     80         maxx(p*2)=add(p);
     81         minn(p*2)=add(p);
     82         //更新左节点 
     83         sum(p*2+1)=add(p)*(r(p*2+1)-l(p*2+1)+1);
     84         maxx(p*2+1)=add(p);
     85         minn(p*2+1)=add(p);
     86         //更新右节点 
     87         add(p*2)=add(p);
     88         //左节点下放lazy 
     89         add(p*2+1)=add(p);
     90         //右节点下放lazy 
     91         add(p)=0;
     92         //lazy清空 
     93     }
     94 }
     95 
     96 void change1(int p,int l,int r,int d) {
     97     //l 到 r 均 +d 
     98     if (l<=l(p)&&r>=r(p)) {
     99         add(p)+=d;
    100         sum(p)+=(long long)d*(r(p)-l(p)+1);
    101         maxx(p)+=d;
    102         minn(p)+=d;
    103         return;
    104     }
    105     spread1(p);
    106     //spread2(p);
    107     int mid=(l(p)+r(p))/2;
    108     if (l<=mid) change1(p*2,l,r,d);
    109     if (r>mid) change1(p*2+1,l,r,d);
    110     sum(p)=sum(p*2)+sum(p*2+1);
    111     maxx(p)=max(maxx(p*2),maxx(p*2+1));
    112     minn(p)=min(minn(p*2),minn(p*2+1));
    113 }
    114 
    115 void change3(int p,int l,int r,int d) {
    116     // l~r 均替换为 d
    117     if (l<=l(p)&&r>=r(p)) {
    118         add(p)=d;
    119         sum(p)=(long long)d*(r(p)-l(p)+1);
    120         maxx(p)=d;
    121         minn(p)=d;
    122         return;
    123     }
    124     //spread1(p);
    125     spread2(p);
    126     int mid=(l(p)+r(p))/2;
    127     if (l<=mid) change3(p*2,l,r,d);
    128     if (r>mid) change3(p*2+1,l,r,d);
    129     sum(p)=sum(p*2)+sum(p*2+1);
    130     maxx(p)=max(maxx(p*2),maxx(p*2+1));
    131     minn(p)=min(minn(p*2),minn(p*2+1)); 
    132 }
    133 
    134 void change2(int p,int x,int v) {
    135     //把 a[x] 值改为 v
    136     if (l(p)==r(p)) {
    137         //叶子节点直接赋值 
    138         sum(p)=v;
    139         maxx(p)=v;
    140         minn(p)=v;
    141         return;
    142     } 
    143     spread1(p);
    144     //spread2(p);
    145     int mid=(l(p)+r(p))/2;
    146     if (x<=mid) change2(p*2,x,v);
    147     else change2(p*2+1,x,v);
    148     sum(p)=sum(p*2)+sum(p*2+1);
    149     maxx(p)=max(maxx(p*2),maxx(p*2+1));
    150     minn(p)=min(minn(p*2),minn(p*2+1));
    151 }
    152 
    153 
    154 ll asksum(int p,int l,int r) {
    155     //查询 l~r 的和 
    156     if (l<=l(p)&&r>=r(p)) return sum(p);
    157     //spread1(p);
    158     spread2(p);
    159     int mid=(l(p)+r(p))/2;
    160     ll val=0;
    161     if (l<=mid) val+=asksum(p*2,l,r);
    162     if (r>mid) val+=asksum(p*2+1,l,r);
    163     return val;
    164 }
    165 
    166 ll askmax(int p,int l,int r) {
    167     //查询 l~r 的最大
    168     if (l<=l(p)&&r>=r(p)) return maxx(p);
    169     //spread1(p);
    170     spread2(p);
    171     int mid=(l(p)+r(p))/2;
    172     ll val=-(1<<30);
    173     if (l<=mid) val=max(val,askmax(p*2,l,r));
    174     if (r>mid) val=max(val,askmax(p*2+1,l,r));
    175     return val;
    176 }
    177 
    178 ll askmin(int p,int l,int r) {
    179     //查询 l~r 的最小
    180     if (l<=l(p)&&r>=r(p)) return minn(p);
    181     //spread(p);
    182     spread2(p);
    183     int mid=(l(p)+r(p))/2;
    184     ll val=(1<<30);
    185     if (l<=mid) val=min(val,askmin(p*2,l,r));
    186     if (r>mid) val=min(val,askmin(p*2+1,l,r));
    187     return val;
    188 }
    189 
    190 /*
    191 int n,m;
    192 char c;
    193 //操作格子1 
    194 int main() {
    195     scanf("%d%d",&n,&m);
    196     for (int i=1;i<=n;i++) {
    197         scanf("%d",&a[i]);
    198     }
    199     build(1,1,n);
    200     for (int i=1,x,y;i<=m;i++) {
    201         cin>>c;
    202         scanf("%d%d",&x,&y);
    203         if (c=='Q') {
    204             ll ansmax=0;
    205             ll ansmin=0;
    206             ll anssum=0;
    207             ansmax=askmax(1,x,y);
    208             ansmin=askmin(1,x,y);
    209             anssum=asksum(1,x,y);
    210             printf("%lld %lld %lld
    ",ansmax,ansmin,anssum);
    211         }
    212         if (c=='U') {
    213             change2(1,x,y);
    214         }
    215     }
    216 
    217     return 0;
    218 }
    219 */
    220 
    221 /*
    222 int n,m;
    223 char op[6];
    224 //操作格子3 
    225 int main () {
    226     scanf("%d%d",&n,&m);
    227     for (int i=1;i<=n;i++) {
    228         scanf("%d",&a[i]);
    229     }
    230     build(1,1,n);
    231     for (int i=1;i<=m;i++) {
    232         cin>>op;
    233         if (op[0]=='S') {
    234             int x,y;
    235             scanf("%d%d",&x,&y);
    236             ll ans=0;
    237             ans=asksum(1,x,y);
    238             printf("%lld
    ",ans);
    239         }
    240         if (op[0]=='A') {
    241             int x,y,z;
    242             scanf("%d%d%d",&x,&y,&z);
    243             change1(1,x,y,z);
    244         }
    245         if (op[0]=='M'&&op[1]=='A') {
    246             int x,y;
    247             scanf("%d%d",&x,&y);
    248             ll ans=0;
    249             ans=askmax(1,x,y);
    250             printf("%lld
    ",ans);
    251         }
    252         if (op[0]=='M'&&op[1]=='I') {
    253             int x,y;
    254             scanf("%d%d",&x,&y);
    255             ll ans=0;
    256             ans=askmin(1,x,y);
    257             printf("%lld
    ",ans);
    258         }
    259     }
    260     
    261     return 0;
    262 }
    263 */
    264 
    265 /*
    266 int n,m;
    267 char op[10];
    268 int main () {
    269     scanf("%d%d",&n,&m);
    270     for (int i=1;i<=n;i++) {
    271         scanf("%d",&a[i]);
    272     }
    273     build(1,1,n);
    274     for (int i=1,x,y,z;i<=m;i++) {
    275         cin>>op;
    276         if (op[0]=='S') {
    277             scanf("%d%d",&x,&y);
    278             ll ans=0;
    279             ans=asksum(1,x,y);
    280             printf("%lld
    ",ans);
    281         }
    282         if (op[0]=='U') {
    283             scanf("%d%d%d",&x,&y,&z);
    284             change3(1,x,y,z);
    285         }
    286         if (op[0]=='M'&&op[1]=='A') {
    287             scanf("%d%d",&x,&y);
    288             ll ans=0;
    289             ans=askmax(1,x,y);
    290             printf("%lld
    ",ans);
    291         }
    292         if (op[0]=='M'&&op[1]=='I') {
    293             scanf("%d%d",&x,&y);
    294             ll ans=0;
    295             ans=askmin(1,x,y);
    296             printf("%lld
    ",ans);
    297         }
    298     }
    299     return 0;
    300 }
    301 */
    302 
    303 int main () {
    304     return 0;
    305 }
  • 相关阅读:
    NVelocity实现违反了LSP法则,使我的一个低级错误排查了一个下午。
    ADO.NET EF 4中 query.Where().Where()和动态组合lambda实现组合查询的不同。
    发现blend4的一个导致崩溃的BUG!!!
    代码回滚:git reset、git checkout和git revert区别和联系
    精确获取函数运行时间,精确到微秒
    在github分支上上传空文件夹
    VS2010 LINK1123:failure during conversion to COFF:file invalid or corrupt
    同步github上fork出来的分支
    未能找到任何适合于指定的区域性或非特定区域性的资源。请确保在编译时已将“XXXXX.resources”正确嵌入或链接到程序集“XX”,或者确保所有需要的附属程序集都可加载并已进行了完全签名。
    决定以后把写博客转的主要平台转到cnblogs了
  • 原文地址:https://www.cnblogs.com/codemaker-li/p/9795395.html
Copyright © 2011-2022 走看看