链接: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; }
主席树
描述
给一个长为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); } } }
描述
给一个空数列,有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; } } }