• ACM模板——线段树&树状数组&ST表


     
    int d[1000006][25];
    int mn[1000006];
    void rmq_init()
    {
        for(int i=1;i<=n;i++)
            d[i][0]=a[i];
        for(int j=1;(1<<j)<=n;j++)
          for(int i=1;i+(1<<j)-1<=n;i++)
            d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
        for(int len=1;len<=n;++len){
            int k=0;
            while((1<<(k+1))<=len)
                k++;
            mn[len]=k;
        }
    }
    int rmq(int L,int R)
    {
        int k=mn[R-L+1];
        return min(d[L][k],d[R-(1<<k)+1][k]);
    }
    ST表
    const int maxn = 504;
    
    int d[maxn][maxn];
    int n;
    void init()
    {
        n = maxn;
        memset(d,0,sizeof(d));
    }
    void update(int x,const int&y,const int&V)
    {
        for(;x<=n;x+=(x&(-x)))
            for(int j = y;j <= n;j += (j&(-j)))
                d[x][j]+=V;
    }
    int getsum(int x,const int &y)
    {
        int res = 0;
        for(;x;x -= x&(-x))
            for(int j = y;j;j-=j&(-j))
                res += d[x][j];
        return res;
    }
    二维树状数组
    const int maxn = 1 << 18;
    
    int n, dat[2*maxn];
    
    void init()
    {
        n = (1 << 18)-2;
        memset(dat,0,sizeof(dat));
    }
    
    //更新第k(0-index)个值为a
    void update(int k,int a)
    {
        k += n+1;
        dat[k] = a;
        while(k>0)
        {
            k = (k-1)/2;
            dat[k] = dat[k*2+1]+dat[k*2+2];
        }
    }
    
    //求[a,b)val
    //query(a,b,0,0,n)
    int query(int a,int b,int k,int l,int r)
    {
        //不相交
        if(r<a || b<l) return 0;
    
        if(a<=l && r<=b) {return dat[k];}
        else
        {
            int vl = query(a,b,k*2+1,l,(l+r)/2);
            int vr = query(a,b,k*2+2,(l+r)/2+1,r);
            
            return vl+vr;
        }
        return -1;//error
    }
    线段树(单点更新区间查询)
     1 #include <bits/stdc++.h>
     2 typedef long long ll;
     3 using namespace std;
     4 #define _for(i,a,b) for(int i = (a);i < b;i ++)
     5 #define _rep(i,a,b) for(int i = (a);i > b;i --)
     6 #define INF 0x3f3f3f3f
     7 #define MOD 1000000007
     8 #define pb push_back
     9 #define maxn 100003
    10 inline ll read()
    11 {
    12     ll ans = 0;
    13     char ch = getchar(), last = ' ';
    14     while(!isdigit(ch)) last = ch, ch = getchar();
    15     while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    16     if(last == '-') ans = -ans;
    17     return ans;
    18 }
    19 inline void write(ll x)
    20 {
    21     if(x < 0) x = -x, putchar('-');
    22     if(x >= 10) write(x / 10);
    23     putchar(x % 10 + '0');
    24 }
    25 int c[500003];
    26 int N,M;
    27 int ask(int x)
    28 {
    29     int ans = 0;
    30     for(; x; x -= x&-x) ans += c[x];
    31     return ans;
    32 }
    33 void add(int x,int y)
    34 {
    35     for(; x <= N; x += x & -x)
    36         c[x]+=y;
    37 }
    38 
    39 int main()
    40 {
    41     N = read();
    42     M = read();
    43     _for(i,1,N+1)
    44     add(i,read());
    45     _for(i,0,M)
    46     {
    47         int op = read();
    48         if(op==2)
    49         {
    50             int l = read();
    51             int r = read();
    52             printf("%d
    ",ask(r)-ask(l-1));
    53         }
    54         else
    55         {
    56             int a = read();
    57             int b = read();
    58             add(a,b);
    59         }
    60     }
    61     return 0;
    62 }
    树状数组(单点更新区间查询)
     1 #include <bits/stdc++.h>
     2 typedef long long ll;
     3 using namespace std;
     4 #define _for(i,a,b) for(int i = (a);i < b;i ++)
     5 #define _rep(i,a,b) for(int i = (a);i > b;i --)
     6 #define INF 0x3f3f3f3f
     7 #define MOD 1000000007
     8 #define pb push_back
     9 #define maxn 100003
    10 inline ll read()
    11 {
    12     ll ans = 0;
    13     char ch = getchar(), last = ' ';
    14     while(!isdigit(ch)) last = ch, ch = getchar();
    15     while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    16     if(last == '-') ans = -ans;
    17     return ans;
    18 }
    19 inline void write(ll x)
    20 {
    21     if(x < 0) x = -x, putchar('-');
    22     if(x >= 10) write(x / 10);
    23     putchar(x % 10 + '0');
    24 }
    25 int c[500003];
    26 int num[500003];
    27 int N,M;
    28 int ask(int x)
    29 {
    30     int ans = 0;
    31     for(; x; x -= x&-x) ans += c[x];
    32     return ans;
    33 }
    34 void add(int x,int y)
    35 {
    36     for(; x <= N; x += x & -x)
    37         c[x]+=y;
    38 }
    39 
    40 void add2(int l,int r,int y)
    41 {
    42     add(l,y);
    43     add(r+1,-y);
    44 } 
    45 int main()
    46 {
    47     N = read();
    48     M = read();
    49     _for(i,1,N+1)
    50         num[i] = read();
    51     _for(i,0,M)
    52     {
    53         int op = read();
    54         if(op==2)
    55         {
    56             int x = read();
    57             printf("%d
    ",num[x]+ask(x));
    58         }
    59         else
    60         {
    61             int l = read();
    62             int r = read();
    63             int y = read();
    64             add2(l,r,y);
    65         }
    66     }
    67     return 0;
    68 }
    树状数组(区间更新单点查询)
      1 #include <bits/stdc++.h>
      2 typedef long long ll;
      3 using namespace std;
      4 #define _for(i,a,b) for(int i = (a);i < b;i ++)
      5 #define _rep(i,a,b) for(int i = (a);i > b;i --)
      6 #define INF 0x3f3f3f3f
      7 #define MOD 1000000007
      8 #define pb push_back
      9 #define maxn 100003
     10 inline ll read()
     11 {
     12     ll ans = 0;
     13     char ch = getchar(), last = ' ';
     14     while(!isdigit(ch)) last = ch, ch = getchar();
     15     while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
     16     if(last == '-') ans = -ans;
     17     return ans;
     18 }
     19 inline void write(ll x)
     20 {
     21     if(x < 0) x = -x, putchar('-');
     22     if(x >= 10) write(x / 10);
     23     putchar(x % 10 + '0');
     24 }
     25 struct segtree
     26 {
     27     int l,r;
     28     ll sum,add;
     29     #define l(x) t[x].l
     30     #define r(x) t[x].r
     31     #define sum(x) t[x].sum
     32     #define add(x) t[x].add
     33 }t[maxn<<2];
     34 int a[maxn];
     35 int N,M;
     36 
     37 void build(int p,int l,int r)
     38 {
     39     l(p) = l,r(p) = r;
     40     if(l==r){sum(p)=a[l];return ;}
     41     int mid = (l+r)/2;
     42     build(p*2,l,mid);
     43     build(p*2+1,mid+1,r);
     44     sum(p) = sum(p*2)+sum(p*2+1);
     45 }
     46 void spread(int p)
     47 {
     48     if(add(p))
     49     {
     50         sum(p*2) += add(p)*(r(p*2)-l(p*2)+1);
     51         sum(p*2+1) += add(p)*(r(p*2+1)-l(p*2+1)+1);
     52         add(p*2) += add(p);
     53         add(p*2+1) += add(p);
     54         add(p) = 0; 
     55     }
     56 }
     57 void change(int p,int l,int r,int d)
     58 {
     59     if(l <= l(p) and r >= r(p))
     60     {
     61         sum(p) += (ll)d * (r(p)-l(p)+1);
     62         add(p) += d;
     63         return ;
     64     }
     65     spread(p);
     66     int mid = (l(p)+r(p))/2;
     67     if(l <= mid)
     68         change(p*2,l,r,d);
     69     if(r > mid)
     70         change(p*2+1,l,r,d);
     71     sum(p) = sum(p*2)+sum(p*2+1);
     72 }
     73 ll ask(int p,int l,int r)
     74 {
     75     if(l <= l(p) and r >= r(p))
     76         return sum(p);
     77     spread(p);
     78     int mid = (l(p)+r(p))/2;
     79     ll val = 0;
     80     if(l <= mid)
     81         val += ask(p*2,l,r);
     82     if(r > mid)
     83         val += ask(p*2+1,l,r);
     84     return val; 
     85 }
     86 int main()
     87 {
     88     N = read();
     89     M = read();
     90     _for(i,1,N+1)
     91         a[i] = read();
     92     build(1,1,N);
     93     _for(i,1,M+1)
     94     {
     95         int op = read();
     96         if(op==1)
     97         {
     98             int l = read();
     99             int r = read();
    100             int y = read();
    101             change(1,l,r,y);
    102         }
    103         else
    104         {
    105             int l = read();
    106             int r = read();
    107             printf("%lld
    ",ask(1,l,r));
    108         }
    109     }
    110     return 0;
    111 }
    线段树(区间更新区间查询)

    ST表的板子是抄的:https://www.cnblogs.com/autsky-jadek/p/7327416.html

  • 相关阅读:
    【LeetCode】面试题59
    【LeetCode】面试题57
    【LeetCode】面试题57
    Chrome查看Markdown并转为PDF
    【LeetCode】232. 用栈实现队列
    【LeetCode】27. 移除元素
    【LeetCode】1323. 6 和 9 组成的最大数字
    【LeetCode】167. 两数之和 II
    第14条:在公有类中使用访问方法而非公有域
    Android Studio项目中三种依赖的添加方式
  • 原文地址:https://www.cnblogs.com/Asurudo/p/10658452.html
Copyright © 2020-2023  润新知