zoukankan      html  css  js  c++  java
  • 复习3-数据结构模板

    1.线段树

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n,p,a,b,m,x,y,ans;
    
    struct node{
        int l,r,w,f;
    }tree[100005];
    
    void build(int l,int r,int o){
        tree[o].l = l,tree[o].r = r;
        if(tree[o].l == tree[o].r) {
            scanf("%d",&tree[o].w);
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,o*2);
        build(mid+1,r,o*2+1);
        tree[o].w = tree[o*2].w + tree[o*2+1].w;
    }
    
    void pushdown(int o){
        tree[o*2].f += tree[o].f;
        tree[o*2+1].f += tree[o].f;
        tree[o*2].w += (tree[o*2].r-tree[o*2].l+1) * tree[o].f;
        tree[o*2+1].w += (tree[o*2+1].r-tree[o*2+1].l+1) * tree[o].f;
        tree[o].f = 0;
    }
    
    void change_point(int o){
        if(tree[o].l == tree[o].r){
            tree[o].w += y;
            return ;
        }
        if(tree[o].f) pushdown(o);
        int mid = (tree[o].l+tree[o].r)/2;
        if(x <= mid) change_point(o*2);
        else change_point(o*2+1);
        tree[o].w = tree[o*2].w + tree[o*2+1].w;
    }
    
    void query_point(int o){
        if(tree[o].l == tree[o].r){
            ans = tree[o].w;
            return ;
        }
        if(tree[o].f)pushdown(o);
        int mid = (tree[o].l + tree[o].r)/2;
        if(x <= mid) query_point(o*2);
        else query_point(o*2+1);
    }
    
    void query_interval(int o){
        if(tree[o].l >= a && tree[o].r <= b){
            ans += tree[o].w;
            return ;
        }
        if(tree[o].f)pushdown(o);
        int mid = (tree[o].l + tree[o].r)/2;
        if(a <= mid) query_interval(o*2);
        if(b > mid) query_interval(o*2+1);
    }
    
    void change_interval(int o){
        if(tree[o].l >= a && tree[o].r <= b){
            tree[o].w += (tree[o].r-tree[o].l+1) * y;
            tree[o].f += y;
            return;
        }
        if(tree[o].f)pushdown(o);
        int mid = (tree[o].l + tree[o].r)/2;
        if(a <= mid) change_interval(o*2);
        if(b > mid) change_interval(o*2+1);
        tree[o].w = tree[o*2].w + tree[o*2+1].w;
    }
    
    int main(){
        scanf("%d",&n);scanf("%d",&m);
        build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&p);
            ans=0;
            
            if(p==2)
            {
                scanf("%d%d",&a,&b);
                query_interval(1);
                printf("%d
    ",ans);
            }
            else
            {
                 scanf("%d%d%d",&a,&b,&y);
                 change_interval(1);
            }
        }
        return 0;
    }
    五种操作

    2.树状数组

    int lowbit(int x){
        return x & -x;
    }
    
    void add(int x,int y)
    {
        for(;x <= n;x += lowbit(x)) c[x] += y;
    }
    
    int query(int x)
    {
        int ans = 0;
        for(;x >= 1;x -= lowbit(x)) ans += c[x];
        return ans;
    }
    单点修改+区间求和
    ll c0[MAXN], c1[MAXN];
      int lowbit(int x){
          return x & -x;
      }
      void add(ll *c, int x, ll k) {
        for(; x <= N; x += lowbit(x)) c[x] += k;
      }
      ll sum(ll *c, int x) { 
        ll r = 0; 
        for(;x >= 1; x -= lowbit(x)) r += c[x];
        return r;
      }
      void add(int l, int r, ll k) {
        add(c0, l, k); add(c0, r + 1, -k);
        add(c1, l, (l - 1) * k); add(c1, r + 1, -r * k);
      }
      ll sum(int l, int r) {
        return sum(c0, r) * r - sum(c1, r) - sum(c0, l - 1) * (l - 1) + sum(c1, l - 1);
      }
    区间修改+区间求和

    3.ST表

    inline int query(int l,int r)
    {
        int tmp = lg[r-l+1];
        return max(dp[l][tmp],dp[r-(1<<tmp)+1][tmp]);
    }
    
    inline void init()
    {
        for(register int i = 1;i <= n;i++)
        dp[i][0] = a[i];
        for(register int j = 1;j < 21;j++)
        {
            for(register int i = 1;i+(1 << j-1) <= n;i++)
            {
                dp[i][j] = max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
            }
        }
        for(register int i = 2;i <= n;i++)
        lg[i] = lg[i >> 1]+1;
    }

    4.并查集

    void init(int n){
        for(int i = 0;i < n;i++)
        {
            father[i] = i;
            high[i] = 0;
        }
    }
    
    int find(int x){
        if(father[x] == x) return x;
        else return father[x] = find(father[x]);
    }
    
    void uniue(int x,int y){
        x = find(x);
        y = find(y);
        if(x == y) return;
        
        if(high[x] < high[y]) father[x] = y;
        else {
            father[y] = x;
            if(high[x] == high[y]) high[x]++;
        }
    }
    
    bool same(int x,int y){
        return find(x) == find(y);
    }
    按秩合并

    5.队列、栈

    //数组实现
    #include <cstdio>
    #define MAXN 2000005
    using namespace std;
    
    struct Num{
        int index,x;//需要记录单调队列内每个数的入队时间(index)和大小(x)
    };
    
    int a[MAXN]; //原数组
    Num q[MAXN]; //单调队列 
    
    int main(void){
        int n,m; //n表示序列长度,m表示滑动窗口长度
        int front,back; //front,back分别表示队头、队尾位置
        //输入
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        //问题解决
        front=1;
        back=0;//初始化队头队尾位置,队头>队尾表示队空
        for (int i=1;i<=n;i++){
            //先输出数a[i]前的最小值
            if (front>back) //q空,即a[i]前没有元素
                printf("0
    ");
            else { //否则判断队头是否需要出队并输出范围内的队头
                if (q[front].index+m<i) //队头已经超出滑动窗口范围
                    front++; // 弹出队头
                printf("%d
    ",q[front].x); //此时队一定非空(想想为什么)
            }
            while (front<=back && q[back].x>=a[i]) 
            //当队列非空时,不断弹出队尾比当前元素大的元素
                back--;
            back++;
            q[back].x=a[i];
            q[back].index=i;//将当前元素入队
            //注意:当前元素无论如何都会入队(想想为什么)
        }
        return 0;
    }
    
    //deque实现
    #include <cstdio>
    #include <queue> // 提供deque
    #define MAXN 2000005
    using namespace std;
    
    struct Num{
        int index,x;//需要记录单调队列内每个数的入队时间(index)和大小(x)
    };
    
    int a[MAXN]; //原数组
    deque<Num> q; //单调队列 
    
    int main(void){
        int n,m; //n表示序列长度,m表示滑动窗口长度
        Num t;//保存当前元素
        //输入
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        //问题解决
        for (int i=1;i<=n;i++){
            //先输出数a[i]前的最小值
            if (q.empty()) //q空,即a[i]前没有元素
                printf("0
    ");
            else { //否则判断队头是否需要出队并输出范围内的队头
                if (q.front().index+m<i) //队头已经超出滑动窗口范围
                    q.pop_front(); // 弹出队头
                printf("%d
    ",q.front().x); //此时队一定非空(想想为什么)
            }
            while ((!q.empty()) && q.back().x>=a[i]) 
            //当队列非空时,不断弹出队尾比当前元素大的元素
                q.pop_back();
            t.index=i;
            t.x=a[i];
            q.push_back(t);//将当前元素入队
            //注意:当前元素无论如何都会入队(想想为什么)
        }
        return 0;
    }
    单调队列
  • 相关阅读:
    Qt 交叉编译经典错误——头文件包含
    Linux-Qt使用QThread多线程isRunning标志量问题
    个人总结——C、C++指针传参和初始化字符空间
    ARM板设置开机自启动应用程序
    python--ModuleFoundError
    php输出错误屏蔽的函数
    类QQ账号生成阐述
    Python基础(四)—日期类型
    Python基础(三)—字典和集合
    Python基础(二)—列表和元组
  • 原文地址:https://www.cnblogs.com/bryce02/p/9931494.html
Copyright © 2011-2022 走看看