樹形結構轉換線性結構的方法(lca倍增)
阿新 • • 發佈:2019-02-17
dfs序是針對某條路徑, 利用根到路徑
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <cstdlib> #include <cmath> #include <stack> #include <map> #include <vector> #include <string> #include <algorithm> const double pi=cos(-1.); const double eps=10e-6; const double eps1=10e-9; const int inf=0x7fffffff; ///const int inf=0x3f3f3f3f; const long long infl=1ll<<62; ///******macro defination******/// #define cas(a) int a; scanf("%d", &a); while (a--) #define cas1(x, a) int a; scanf("%d", &a); for (int x=1; x<=a; ++x) #define int(a) int a; scanf("%d", &a) #define char(a) char a; scanf("%c", &a) #define strr(a, x) char a[x]; scanf("%s", &a) #define clean(a, x) memset (a, x, sizeof(a)); #define copy(a, b) memcpy(a, b, sizeof(a)); #define up(x,a) for(int x=0; x<a; ++x) #define down(x,a) for(int x=a-1; x>=0; --x) #define up1(x,a) for (int x=1; x<=a; ++x) #define debug(a) printf("here is %d!!!\n", a); ///*** mathmatics ***/// #define sqr(x) (x)*(x) #define abs(x) (x)>0?(x):(-(x)) #define zero(x) (x)<eps && (x)>eps #define lowbit(x) ((x)&(-(x))) ///*** for STL ***/// #define fst first #define scd second #define pb push_back #define mp makepair #define lb lower_bound #define ub upper_bound ///****** by Geners ******/// typedef long long ll; typedef unsigned int UI; using namespace std; const int mod=1000000007; const int maxn=100000+123; #define vex edge[p].v int w[maxn]; struct Edge{int v, next;}edge[2*maxn]; int head[maxn], cnt; void addedge(int u, int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } ///*** graphic theory***/// ll C[2*maxn]; int N; int Query(int x){ for (int res=0; ; res+=C[x], x-=lowbit(x))if(x==0)return res; } void Update(int x, int v){ for (;x<=N; x+=lowbit(x))C[x]+=v; } void IUpdate(int s, int t, int v){ Update(t+1, -v); Update(s, v); } ///*** Binary Indexed Tree ***/// int node[maxn]; int d[maxn], fath[maxn][50], l[maxn], r[maxn], idx; void dfs(int u, int fa) { l[u]=++idx; for (int p=head[u]; ~p; p=edge[p].next) { if(vex==fa)continue; fath[vex][0]=u; int pa=u; d[vex]=d[u]+1; for (int k=0; fath[pa][k]; ++k) { fath[vex][k+1]=fath[pa][k]; pa=fath[pa][k]; } dfs(vex, u); } r[u]=++idx; } int LCA(int u, int v) { if(u==v)return u; if(d[u]<d[v])swap(u, v); int m=d[u]-d[v];/// 將 u, v 調到同深度 for (int i=0; m; m>>=1, ++i)if(m&1)u=fath[u][i]; if(u==v)return u; for (int i=0; u^v; ) { if(fath[u][i]!=fath[v][i] || (fath[u][i]==fath[v][i] && i==0)) u=fath[u][i], v=fath[v][i], ++i; else --i; } return u; } void init() { clean(head, -1); cnt=0; clean(C, 0); clean(fath, 0); } int main () { int n, m, q; while (~scanf("%d%d%d", &n, &m, &q)) { init(); for (int i=1; i<=n; ++i) { scanf("%d", node+i); } for (int i=0; i<m; ++i) { int a, b; scanf("%d%d", &a, &b); addedge(a, b); addedge(b, a); } d[1]=0; idx=0; dfs(1, -1); N=n<<1; for (int i=0; i<q; ++i) { char op[5]; scanf("%s", op); if(op[0]=='I' || op[0]=='D') { int a, b, c; scanf("%d%d%d", &a, &b, &c); if(op[0]=='D')c=-c; ///debug(l[a]); IUpdate(1, l[a], c); IUpdate(1, l[b], c); int lca=LCA(a, b); ///debug(lca); IUpdate(1, l[lca], -c); if(lca!=1)IUpdate(1, l[lca]-1, -c); } if(op[0]=='Q') { int a; scanf("%d", &a); int d=Query(l[a])-Query(r[a]); printf("%d\n", node[a]+d); } } } return 0; }
用樹狀陣列, 單點修改的點取左端點座標, 左右端點的意義為 左端點為當前點, 直到右端點位置都是該點的子樹
因此查詢子樹的操作變為對某點對應左右端點的查詢
#define vex edge[p].v int w[maxn]; struct Edge{int v, next;}edge[2*maxn]; int head[maxn], cnt; void addedge(int u, int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } ///*** graphic theory***/// int C[2*maxn]; int N; int Query(int x){ for (int res=0; ; res+=C[x], x-=lowbit(x))if(x==0)return res; } void Update(int x, int v){ for (;x<=N; x+=lowbit(x))C[x]+=v; } ///---------------- ///---------------- void IUpdate(int s, int t, int v){ Update(t+1, -v); Update(s, v); } ///*** Binary Indexed Tree ***/// int idx, l[maxn], r[maxn]; void dfs(int u, int fa) { l[u]=++idx; for (int p=head[u]; ~p; p=edge[p].next) { if(vex==fa)continue; dfs(vex, u); } r[u]=idx; } void init() { clean (head, -1); cnt=0; idx=0; } int main () { int n, k; while (~scanf("%d", &n)) { init(); for (int i=1; i<n; ++i) { int a, b; scanf("%d%d", &a, &b); addedge(a, b); addedge(b, a); } idx=0; dfs(1, -1); //for (int i=1; i<=idx; ++i)printf("l %d %d %d\n", i, l[i], r[i]); N=idx; clean(C, 0); for (int i=1; i<=idx; ++i) Update(i, 1); int q; scanf("%d", &q); while (q--) { char op[5]; int a; scanf("%s%d", op, &a); if(op[0]=='C') { //printf("%d", t); int t=Query(l[a])-Query(l[a]-1); t=(t^1)-t; // printf(" %d\n", t); Update(l[a], t); }else { printf("%d\n", Query(r[a])-Query(l[a]-1)); } } } return 0; }