1. 程式人生 > >樹形結構轉換線性結構的方法(lca倍增)

樹形結構轉換線性結構的方法(lca倍增)

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;
}