数据结构之树形结构

链接:http://cdqz.openjudge.cn/ds/

树状数组:

描述

给一个长为N的数列,有M次操作,每次操作是以下两种之一:

(1)修改数列中的一个数

(2)求数列中某位置的值

输入第一行两个正整数N和M。
第二行N个整数表示这个数列。
接下来M行,每行开头是一个字符,若该字符为'M',则表示一个修改操作,接下来两个整数x和y,表示把x位置的值修改为y;若该字符为'Q',则表示一个询问操作,接下来一个整数x,表示求x位置的值。输出对每一个询问操作单独输出一行,表示答案。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
int a[maxn],b[maxn],c[maxn];
int n,m;
int lowbit(int x){
    return x&(-x);
}
void add(int a,int x){
    while(x <= n){
        c[x] += a;
        x += lowbit(x);
    }
}
int query(int x){
    int rt = 0;
    while(x > 0){
        rt += c[x];
        x -= lowbit(x);
    }
    return rt;
}
int main()
{

    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++){
        scanf("%d", a + i);
        b[i] = a[i] - a[i - 1];
        add(b[i], i);
    }
    while(m--){
        char opt;
        cin>>opt;
        if(opt == 'Q'){
            int x;
            scanf("%d",&x);
            printf("%d
",query(x));
        }
        else {
            int x,y;
            scanf("%d%d",&x,&y);
            add(y - a[x], x);
            add(a[x] - y, x + 1);
            a[x] = y;
        }

    }
    return 0;
}
View Code

主席树

描述

给一个长为N的数列,有M次操作,每次操作是以下两种之一:

(1)修改数列中的一个数

(2)求数列中某位置在某次操作后的值

输入第一行两个正整数N和M。
第二行N个整数表示这个数列。
接下来M行,每行开头是一个字符,若该字符为'M',则表示一个修改操作,接下来两个整数x和y,表示把x位置的值修改为y;若该字符为'Q',则表示一个询问操作,接下来两个整数x和y,表示求x位置在第y次操作后的值。输出对每一个询问操作单独输出一行,表示答案。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
int n, m, a[maxn];
struct Node{
    int v;
    Node *ls, *rs;
}pool[30* maxn], *root[maxn], *zero ,*tail = pool ;
void build(){
    zero = ++tail;
    zero->ls = zero->rs = zero;
    zero->v = 0;
    root[0] = zero;
}
Node * newnode(int val){
    Node *nd = ++tail;//要有++tail 
    nd->v = val;
    nd->ls = nd->rs = zero;
    return nd;
}
#define Ls nd->ls, l, m
#define Rs nd->rs, m+1, r
Node * modify(int pos, int val, Node *nd, int l = 1, int r = n){
    Node *nnd = ++tail;
    if(l == r)nnd = newnode(val);
    else{
        int m = (l + r) >> 1;
        if(pos <= m){
            nnd->rs = nd->rs;
            nnd->ls = modify(pos, val, Ls);
        }
        else{
            nnd->ls = nd->ls;
            nnd->rs = modify(pos, val, Rs);
        }
    }
    return nnd;
}
int query(int pos, Node *nd, int l = 1, int r = n ){
    if(nd == zero)return 0;
    if(l == r)
        return nd->v;
    else {
        int m = (l + r) >> 1;
        if(pos <= m)return query(pos, Ls);
        else return query(pos, Rs);
    }
}
Node * print(int pos,Node * nd,int i){
    printf("%d
",query(pos,nd));
    return root[i-1];
}
int main(){ 

    scanf("%d%d",&n,&m);
    build();
    for(int i = 1; i <= n; i++){
        scanf("%d",a+i);
        root[0] = modify(i,a[i],root[0]);
        
    }
    
    for(int i = 1; i <= m; i++){
        char opt;
        cin>>opt;
        if(opt == 'M'){
            int pos,val;
            scanf("%d%d",&pos,&val);
            root[i] = modify(pos,val,root[i-1]);
        }
        else {
            int t,pos;
            scanf("%d%d",&pos,&t);
            root[i] = print(pos,root[t],i);
        }
    }

}
View Code

描述

给一个空数列,有M次操作,每次操作是以下三种之一:

(1)在数列后加一个数

(2)求数列中某位置的值

(3)撤销掉最后进行的若干次操作(1和3)

输入第一行一个正整数M。
接下来M行,每行开头是一个字符,若该字符为'A',则表示一个加数操作,接下来一个整数x,表示在数列后加一个整数x;若该字符为'Q',则表示一个询问操作,接下来一个整数x,表示求x位置的值;若该字符为'U',则表示一个撤销操作,接下来一个整数x,表示撤销掉最后进行的若干次操作。输出对每一个询问操作单独输出一行,表示答案。

#include<bits/stdc++.h>
using namespace std;
#define M 1000000007
#define ll long long
#define maxn 100008
int len, n, s, L[maxn], a[maxn];
struct Node{
    int v;
    Node *ls, *rs;
}pool[maxn * 32], *tail = pool, *root[maxn];
#define Ls nd->ls, l, m
#define Rs nd->rs, m+1, r
Node * build(int l = 1, int r = n){
    Node *nd = ++tail;
    if(l == r)nd -> v = 0;
    else {
        int m = (l + r) >> 1;
        nd -> ls = build(l, m);
        nd -> rs = build(m+1, r);
    }
    return nd;
}
int query(int pos, Node *nd, int l = 1, int r = n){
    if(l == r)return nd -> v;
    int m = (l + r) >> 1;
    if(pos <= m)return query(pos, Ls);
    else return query(pos, Rs);    
}
Node * modify(int val, int pos, Node *nd, int l = 1, int r = n){
    Node * nnd = ++tail;
    if(l == r)nnd -> v = val;
    else {
        int m = (l + r) >> 1;
        if(pos <= m){
            nnd -> rs = nd -> rs;
            nnd -> ls = modify(val, pos, Ls);
        }
        else {
            nnd -> ls = nd -> ls;
            nnd -> rs = modify(val, pos, Rs);
        }
    }
    return nnd;
}
Node * Query(int pos, Node * nd){    
    printf("%d
",query(pos, nd));
    return nd;
}
Node * Modify(int val, int pos, Node * nd){
    return modify(val, pos, nd);
}
Node * back(int t){    
    return root[t];
}
int main(){
    scanf("%d%d",&n);
    int cz = 0;
    root[0] = build();
    for(int i = 1; i <= n; i++){
        char opt;
        cin>>opt;
        int x;
        if(opt == 'A'){
            scanf("%d",&x);
            L[i] = L[i-1] + 1;
            root[i] = Modify(x, L[i], root[i-1]);
            a[++cz] = i;
        }
        else if(opt == 'Q'){
            scanf("%d",&x);
            L[i] = L[i-1];
            root[i] = Query(x, root[i-1]);
        }
        else {
            scanf("%d",&x);
            L[i] = L[a[cz - x]];
            root[i] = back(a[cz - x]);
            a[++cz] = i;
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/EdSheeran/p/8723473.html