小清的樹鏈剖分10題日誌01 樹鏈剖分種果子 有你好果子喫的

聲明:由於本人能力尚不優 故無法做出解釋文章 此文僅爲自己日記 感謝你的閱讀
作爲隊裏的數據結構選手 2019西安邀請賽的E題 竟然在有機時的情況下 想到了線段樹log^2的拆位做法 但是題目路徑把自己問懵逼了 啥? 啥是最短路? 點和點之間最短路是啥?
於是 這名數據結構小菜雞隻好回來惡補某個維護樹上點和點直接最短路的東西 ---- 叔臉剖分(這名數據結構小菜雞沒臉啦

ZJOI2008 樹的統計

我們只要維護一下一個max 和 sum 即可輕鬆AC

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 30025;
int arr[MAX_N],p[MAX_N],top[MAX_N],eid,cnt,Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],maxx[MAX_N<<2],s[MAX_N<<2],depth[MAX_N],fa[MAX_N];
int n;
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v =v ;
    e[eid].next = p[u];
    p[u] = eid++;
}
int Max(int a,int b){return a > b?a:b;}
void up(int rt)
{
    maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
    s[rt] = s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        s[rt] = maxx[rt] = arr[Rank[l]];
        return;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void update(int rt,int l,int r,int x,int v)
{
    if(l==r)
    {
        maxx[rt] = s[rt] = v;
        return;
    }
    int mid = (l+r)>>1;
    if(x<=mid) update(rt<<1,l,mid,x,v);
    else update(rt<<1|1,mid+1,r,x,v);
    up(rt);
}
int query(int rt,int l,int r,int x,int y,int flag)
{
    if(x<=l&&r<=y)
    {
        if(flag==0) return maxx[rt];
        return s[rt];
    }
    int mid = (l+r)>>1;
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);
    else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);
    else
    {
        if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
        return query(rt<<1,l,mid,x,y,flag)+query(rt<<1|1,mid+1,r,x,y,flag);
    }
}
void dfs1(int x,int fath)
{
    fa[x] = fath;
    depth[x] = depth[fath]+1;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt] = u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int  v= e[i].v;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
int Sum(int x,int y)
{
    int ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans+=query(1,1,n,id[top[x]],id[x],1);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans+=query(1,1,n,id[x],id[y],1);
    return ans;
}
int sum(int x,int y)
{
    int ans = -30001;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans = Max(ans,query(1,1,n,id[top[x]],id[x],0));
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans = Max(ans,query(1,1,n,id[x],id[y],0));
    return ans;
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int a,b,m,x,y;
    n = read();
    char opt[25];
    init();
    for(int i = 1;i<n;++i)
    {
        a = read();b=read();
        add(a,b);add(b,a);
    }
    for(int i = 1;i<=n;++i) arr[i] = read();
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    m = read();
    for(int i = 1;i<=m;++i)
    {
        scanf("%s",opt);
        if(opt[0]=='C')
        {
            x = read();y=read();
            update(1,1,n,id[x],y);
        }
        else
        {
            if(opt[1]=='M')
            {
                x = read();y = read();
                printf("%d\n",sum(x,y));
            }
            else
            {
                x = read();y=read();
                printf("%d\n",Sum(x,y));
            }
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

cogs1612

用到了樹鏈剖分的第一個dfs序 因爲dfs序是連續的 你記得用小的-1 而不是大的dfn 因爲這兩個父子可能不相連 舉個例子 父親的右兒子 因爲這個WA了一發

//http://cogs.pro:8080/cogs/problem/problem.php?pid=vXNzykekV
/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100025;
int a[MAX_N],b[MAX_N],p[MAX_N],eid,cnt,low[MAX_N],sz[MAX_N],depth[MAX_N],Rank[MAX_N],Point[MAX_N],high[MAX_N];
ll arr[MAX_N];
ll Max(ll a,ll b) {return a>b?a:b;}
ll Min(ll a,ll b) {return a<b?a:b;}
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int next,v,d;
}e[MAX_N<<1];
void add(int u,int v,int d)
{
    e[eid].d = d;
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void dfs(int x,int fa)
{
    sz[x] = 1;
    depth[x] = depth[fa]+1;
    low[x] = ++cnt;
    Rank[cnt] = x;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v  = e[i].v;
        if(v==fa) continue;
        Point[e[i].d] = v;
        dfs(v,x);
        sz[x]+=sz[v];
    }
    high[x] = cnt;
}


namespace sgt
{
    #define mid ((l+r)>>1)
    ll maxx[MAX_N<<2],minn[MAX_N<<2];
    void up(int rt)
    {
        maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
        minn[rt] = Min(minn[rt<<1],minn[rt<<1|1]);
    }
    void build(int rt,int l,int r)
    {
        if(l==r)
        {
            maxx[rt] = minn[rt] = arr[Rank[l]];
            return;
        }
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        up(rt);
    }
    void update(int rt,int l,int r,int x,int v)
    {
        if(l==r)
        {
            maxx[rt] = minn[rt] = v;
            return;
        }
        if(x<=mid) update(rt<<1,l,mid,x,v);
        else update(rt<<1|1,mid+1,r,x,v);
        up(rt);
    }
    ll query(int rt,int l,int r,int x,int y,int flag)
    {
        if(x>y) if(flag==0) return 0;
        else return 100000005ll;
        if(x<=l&&r<=y)
        {
            if(flag==0) return maxx[rt];
            return minn[rt];
        }
        if(x>mid) return query(rt<<1|1,mid+1,r,x,y,flag);
        else if(y<=mid) return query(rt<<1,l,mid,x,y,flag);
        else
        {
            if(flag==0) return Max(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
            return Min(query(rt<<1,l,mid,x,y,flag),query(rt<<1|1,mid+1,r,x,y,flag));
        }
    }
    #undef mid
}

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    freopen("westward.in","r",stdin);
    freopen("westward.out","w",stdout);
    int x,y,n,Q;
    char opt[25];
    n = read();Q = read();
    for(int i = 1;i<=n;++i) scanf("%lld",&arr[i]);
    init();
    for(int i = 1;i<n;++i)
    {
        a[i] = read();b[i] = read();
        add(a[i],b[i],i);add(b[i],a[i],i);
    }
    dfs(1,0);
    sgt::build(1,1,n);
    for(int i = 1;i<=Q;++i)
    {
        scanf("%s",opt);
        if(opt[0]=='Q')
        {
            x =  read();
            ll maxx1,maxx2,minn1,minn2;
            int P = a[x],P_ = b[x];
            if(low[P]>low[P_]) swap(P,P_);
            maxx1 = Max(sgt::query(1,1,n,1,low[P_]-1,0),sgt::query(1,1,n,high[P_]+1,n,0));
            minn1 = Min(sgt::query(1,1,n,1,low[P_]-1,1),sgt::query(1,1,n,high[P_]+1,n,1));
            maxx2 = sgt::query(1,1,n,low[P_],high[P_],0);
            minn2 = sgt::query(1,1,n,low[P_],high[P_],1);
            printf("%lld\n",minn1*maxx1+minn2*maxx2);
        }
        else
        {
            x = read();y= read();
            sgt::update(1,1,n,low[x],y);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

BZOJ2243
這題數顏色 大家是不是對線段樹統計顏色部分都會
然後爲了讓我們好寫 我們順便用樹鏈剖分維護一下lca
這樣你就不用swap 因爲你一旦swap 顏色左右必須要考慮
你考慮兩個點各自到lca 因爲從底向上 所以不用swap

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}

/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/
const int MAX_N = 100025;
int n,cnt,s[MAX_N<<2],rnum[MAX_N<<2],lnum[MAX_N<<2],col[MAX_N<<2],p[MAX_N],eid ,fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],Rank[MAX_N],top[MAX_N],id[MAX_N],arr[MAX_N];
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
void up(int rt)
{
    lnum[rt] = lnum[rt<<1];
    rnum[rt] = rnum[rt<<1|1];
    if(lnum[rt<<1|1]==rnum[rt<<1]) s[rt] = s[rt<<1]+s[rt<<1|1]-1;
    else s[rt] = s[rt<<1] +s[rt<<1|1];
}
void build(int rt,int l,int r)
{
    col[rt] = lnum[rt] = rnum[rt] = -1;s[rt] = 0;
    if(l==r)
    {
        lnum[rt] = rnum[rt] = arr[Rank[l]];
        s[rt] = 1;
        return ;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void down(int rt,int l,int r)
{
    if(col[rt]!=-1)
    {
        col[rt<<1] = col[rt<<1|1] = col[rt];
        s[rt<<1] = s[rt<<1|1] = 1;
        lnum[rt<<1] = lnum[rt<<1|1] = rnum[rt<<1] = rnum[rt<<1|1] = col[rt];
        col[rt] = -1;
    }
}
void update(int rt,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y)
    {
        lnum[rt] = rnum[rt] = col[rt] = v;
        s[rt] = 1;
        return ;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v);
    else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
    up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return s[rt];
    }
    int mid = (l+r)>>1;
    down(rt,l,r);
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) return query(rt<<1,l,mid,x,y);
    else
    {
        if(lnum[rt<<1|1]==rnum[rt<<1]) return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y) - 1);
        else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
    }
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v =v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void dfs1(int x,int fath)
{
    sz[x] = 1;
    depth[x] = depth[fath]+1;
    fa[x] = fath;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[v]>sz[son[x]]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt] = u;
    if(!son[u])
        return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
void updates(int x,int y,int c)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]])
            swap(x,y);
        update(1,1,n,id[top[x]],id[x],c);
        x = fa[top[x]];
    }
    if(id[x]>id[y])
        swap(x,y);
    update(1,1,n,id[x],id[y],c);
}
int getl(int rt,int l,int r,int x)
{
    if(l==r)
    {
        return lnum[rt];
    }
    int mid = (l+r)>>1;
    down(rt,l,r);
    if(x<=mid) return getl(rt<<1,l,mid,x);
    else return getl(rt<<1|1,mid+1,r,x);
}
inline int lca(int x,int y){
    int f1=top[x],f2=top[y];
    while(f1!=f2) {
    if(depth[f1]<depth[f2]) swap(f1,f2),swap(x,y);
    x=fa[f1]; f1=top[x];
    }
    if(depth[x]<depth[y]) swap(x,y);
    return y;
}
int sum(int x,int y)
{
    int ans = 0,last = -1,now = -1;
    while(top[x]!=top[y])
    {
        now = getl(1,1,n,id[x]);
        ans += query(1,1,n,id[top[x]],id[x]);
        if(now==last) ans--;
        last = getl(1,1,n,id[top[x]]);
        x = fa[top[x]];
    }
    ans+=query(1,1,n,id[y],id[x]);
    now = getl(1,1,n,id[x]);
    if(now==last) ans--;
    return ans;
}
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,b,x,y,v;
    char opt[5];
    n = read();m = read();
    init();
    for(int i = 1;i<=n;++i) arr[i] = read();
    for(int i = 1;i<n;++i)
    {
        a = read();b=read();
        add(a,b);add(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    for(int i = 1;i<=m;++i)
    {
        scanf("%s",opt);
        if(opt[0]=='C')
        {
            x = read();y=read();v=read();
            updates(x,y,v);
        }
        else
        {
            x = read();y = read();
            int LCA = lca(x,y);
            int ans = sum(x,LCA)+sum(y,LCA);
            printf("%d\n",ans-1);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

BZOJ4538
這題應該是我目前熟練剖分做過最難的題了
我們需要維護的是 不經過某段路徑的最大值 然後用兩個堆
壓入堆 和刪除堆 刪除就是看兩個堆頂是不是相同
否則輸出壓入堆的堆頂
注意 維護的是是不經過某段路徑的最大值 這樣你在問就可以直接問出來了

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100011;
const int MAX_M = 200011;
int fa[MAX_N],sz[MAX_N],depth[MAX_N],son[MAX_N],top[MAX_N],id[MAX_N],p[MAX_N],eid,n,ans,cnt;
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
struct priority_tree
{
    priority_queue<int> q1,q2;
    inline void push1(int x) {q1.push(x);}
    inline void push2(int x) {q2.push(x);}
    inline int top(){
        int res = -1;while(!q2.empty()&&(q1.top()==q2.top())) q1.pop(),q2.pop();
        if(!q1.empty()) res = q1.top();
        return res;
    }
}s[MAX_N<<2];
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/
void dfs1(int x,int fath)
{
    sz[x] = 1;
    fa[x] = fath;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        depth[v] = depth[x]+1;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<=sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
struct node
{
    int l,r;
    bool operator <(const node other) const
    {
        return l < other.l;
    }
}B[MAX_N];
void update(int rt,int l,int r,int x,int y,int v,int flag)
{
    if(x<=l&&r<=y)
    {
        if(flag==0) s[rt].push1(v);
        else s[rt].push2(v);
        return;
    }
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);
    else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
}
void updates(int x,int y,int c,int flag)
{
    int f1 = top[x],f2 = top[y],scnt = 0;
    while(f1!=f2)
    {
        if(depth[f1]<depth[f2])
            swap(x,y),swap(f1,f2);
        B[++scnt].r = id[x],B[scnt].l = id[f1];
        x = fa[f1];f1 = top[x];
    }
    if(depth[x]<depth[y])
        swap(x,y);
    B[++scnt].r = id[x],B[scnt].l = id[y];
    int last = 0;sort(B+1,B+1+scnt);
    for(int i = 1;i<=scnt;++i)
    {
        if(B[i].l-1>=last+1) update(1,1,n,last+1,B[i].l-1,c,flag);
        last = B[i].r;
    }
    if(n>=last+1) update(1,1,n,last+1,n,c,flag);
}
void query(int rt,int l,int r,int x)
{
    ans = max(ans,s[rt].top());
    if(l==r) return ;
    int mid = (l+r)>>1;
    if(x<=mid) query(rt<<1,l,mid,x);
    else query(rt<<1|1,mid+1,r,x);
}
/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/
struct Query{
    int x,y,v;
}Q[MAX_M];

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,b,ljq,x,y,v;
    init();
    n = read();m = read();
    for(int i = 1;i<n;++i)
    {
        a=read();b=read();
        add(a,b);add(b,a);
    }
    depth[1] = 1;dfs1(1,0);
    cnt = 0;dfs2(1,1);
    for(int i = 1;i<=m;++i)
    {
        ljq = read();
        if(ljq==0)
        {
            x = read();y =read();v=read();
            Q[i].x = x;Q[i].y = y;Q[i].v = v;
            updates(x,y,v,0);
        }
        else if(ljq==1)
        {
            v = read();
            updates(Q[v].x,Q[v].y,Q[v].v,1);
        }
        else
        {
            v = read();
            ans = -1;
            query(1,1,n,id[v]);
            printf("%d\n",ans);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

P3833
樹鏈剖分亂搞

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}

/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/
const int MAX_N = 100025;
ll s[MAX_N<<2],col[MAX_N<<2];
int n,p[MAX_N],cnt,eid,id[MAX_N],son[MAX_N],depth[MAX_N],sz[MAX_N],fa[MAX_N],Rank[MAX_N],top[MAX_N];
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v=  v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void up(int rt)
{
    s[rt]  =s[rt<<1]+s[rt<<1|1];
}
void build(int rt,int l,int r)
{
    s[rt]  = col[rt] = 0;
    if(l==r)
    {
        return;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void down(int rt,int l,int r)
{
    if(col[rt])
    {
        int mid = (l+r)>>1;
        col[rt<<1]+=col[rt];
        col[rt<<1|1]+=col[rt];
        s[rt<<1]+=1ll*(mid-l+1)*col[rt];
        s[rt<<1|1] += 1ll*(r-mid)*col[rt];
        col[rt] = 0;
    }
}
void update(int rt,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y)
    {
        col[rt]+=v;
        s[rt]+=1ll*(r-l+1)*v;
        return;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v);
    else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
    up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return s[rt];
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) return query(rt<<1,l,mid,x,y);
    else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
    depth[x] = depth[fath]+1;
    fa[x] = fath;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt] = u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
void updates(int x,int y,int c)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]])
            swap(x,y);
        update(1,1,n,id[top[x]],id[x],c);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update(1,1,n,id[x],id[y],c);
}
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,b,v;
    char opt[5];
    n = read();
    init();
    for(int i = 1;i<n;++i)
    {
        a = read();b=read();a++,b++;
        add(a,b);add(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    m = read();
    for(int i = 1;i<=m;++i)
    {
        scanf("%s",opt);
        if(opt[0]=='A')
        {
            a = read();b=read();v=read();a++;b++;
            updates(a,b,v);
        }
        else
        {
            a = read();a++;
            printf("%lld\n",query(1,1,n,id[a],id[a]+sz[a]-1));
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

BZOJ4196
你只要發現 安裝都是從這個點到1
刪除都是這個點的兒子那麼你就很容易搞了

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100025;
int n,eid,p[MAX_N],cnt,id[MAX_N],s[MAX_N<<2],col[MAX_N<<2],sz[MAX_N],depth[MAX_N],fa[MAX_N],top[MAX_N],son[MAX_N];
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void up(int rt)
{
    s[rt] = s[rt<<1]+s[rt<<1|1];
}
void down(int rt,int l,int r)
{
    if(col[rt]!=-1)
    {
        int mid = (l+r)>>1;
        s[rt<<1] = (mid-l+1)*col[rt];
        s[rt<<1|1] = (r-mid)*col[rt];
        col[rt<<1] = col[rt<<1|1] = col[rt];
        col[rt] = -1;
    }
}
void build(int rt,int l,int r)
{
    col[rt] = -1;
    if(l==r) {s[rt] = 1;return;}
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void update(int rt,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y)
    {
        col[rt] = v;
        s[rt] = (r-l+1)*v;
        return;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v);
    else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
    up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return s[rt];
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) return query(rt<<1,l,mid,x,y);
    else return (query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
    sz[x] = 1;
    depth[x] = depth[fath]+1;
    fa[x] = fath;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
int sum(int x,int y)
{
    int ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans+=query(1,1,n,id[top[x]],id[x]);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans+=query(1,1,n,id[x],id[y]);
    return ans;
}
void updates(int x,int y,int c)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]] < depth[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],c);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,x;char opt[20];
    n = read();
    init();
    for(int i = 2;i<=n;++i)
    {
        a = read();a++;
        add(a,i);add(i,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    m = read();
    for(int i = 1;i<=m;++i)
    {
        scanf("%s%d",opt,&x);
        x++;
        if(opt[0]=='i')
        {
            printf("%d\n",sum(1,x));
            updates(1,x,0);
        }
        else
        {
            printf("%d\n",sz[x]- query(1,1,n,id[x],id[x]+sz[x]-1));
            update(1,1,n,id[x],id[x]+sz[x]-1,1);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

P3398
思路也很簡單 你區間賦個值 再查一下就行了
以前不會樹鏈剖分這種題估計都要哭爹喊娘了

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100025;
int Max(int a,int b){return a >b?a:b;}
int n,p[MAX_N],eid,cnt,id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],maxx[MAX_N<<2],col[MAX_N<<2],top[MAX_N],depth[MAX_N];
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void up(int rt)
{
    maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{
    maxx[rt] = 0;col[rt] = -1;
    if(l==r) return;
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void down(int rt,int l,int r)
{
    if(col[rt]!=-1)
    {
        maxx[rt<<1] = maxx[rt<<1|1] = col[rt];
        col[rt<<1] = col[rt<<1|1] = col[rt];
        col[rt] = -1;
    }
}
void update(int rt,int l,int r,int x,int y,int v)
{
    if(x<=l&&r<=y)
    {
        maxx[rt] = v;
        col[rt] = v;
        return ;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v);
    else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v);
    up(rt);
}
int query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        return maxx[rt];
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) return query(rt<<1,l,mid,x,y);
    else return Max(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
    depth[x] = depth[fath]+1;
    fa[x] = fath;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    }
}
int sum(int x,int y)
{
    int ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans = Max(ans,query(1,1,n,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans = Max(ans,query(1,1,n,id[x],id[y]));
    return ans;
}
void updates(int x,int y,int c)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],c);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update(1,1,n,id[x],id[y],c);
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,a,b,x,y;
    n = read();m = read();
    init();
    for(int i = 1;i<n;++i)
    {
        a = read();b=read();
        add(a,b);add(b,a);
    }
    build(1,1,n);
    dfs1(1,0);
    dfs2(1,1);
    for(int i = 1;i<=m;++i)
    {
        a = read();b=read();x=read();y=read();
        updates(a,b,1);
        if(sum(x,y)==1) printf("Y\n");
        else printf("N\n");
        updates(a,b,0);
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

BZOJ3531
這個題也是十分的騷呢 首先十分好想到對每個宗教都維護一顆線段樹 大膽的建樹 也就100000棵樹吧糟糕 MLE了 那麼就上動態開點啊 反正他最多有100000個人

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
int Max(int a,int b){return a>b?a:b;}
const int MAX_N = 100025;
const int N = 100000;
int p[MAX_N],now,eid,cnt,Rank[MAX_N],depth[MAX_N],top[MAX_N],id[MAX_N],belong[MAX_N],arr[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],root[MAX_N],maxx[MAX_N<<5],s[MAX_N<<5],lson[MAX_N<<5],rson[MAX_N<<5];
void init()
{
    eid = 0;
    memset(p,-1,sizeof(p));
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void update(int &rt,int l,int r,int x,int v)
{
    if(!rt)
    {
        rt = ++now;
        maxx[rt] = s[rt] = v;
    }
    if(l==r)
    {
        maxx[rt] = v;
        s[rt] = v;
        return;
    }
    int mid = (l+r)>>1;
    if(x<=mid) update(lson[rt],l,mid,x,v);
    else update(rson[rt],mid+1,r,x,v);
    maxx[rt] = Max(maxx[lson[rt]],maxx[rson[rt]]);
    s[rt] = s[lson[rt]]+s[rson[rt]];
}
int query(int rt,int l,int r,int x,int y)
{
    if(!rt) return 0;
    if(x<=l&&r<=y)
    {
        return s[rt];
    }
    int mid =  (l+r)>>1;
    if(x>mid) return query(rson[rt],mid+1,r,x,y);
    else if(y<=mid) return query(lson[rt],l,mid,x,y);
    else return query(lson[rt],l,mid,x,y)+query(rson[rt],mid+1,r,x,y);
}
int Query(int rt,int l,int r,int x,int y)
{
    if(!rt) return 0;
    if(x<=l&&r<=y) return maxx[rt];
    int mid = (l+r)>>1;
    if(x>mid) return Query(rson[rt],mid+1,r,x,y);
    else if(y<=mid) return Query(lson[rt],l,mid,x,y);
    else return Max(Query(lson[rt],l,mid,x,y),Query(rson[rt],mid+1,r,x,y));
}
void dfs1(int x,int fath)
{
    fa[x] = fath;
    depth[x] = depth[fath]+1;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt] = u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v= e[i].v;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
int Sum(int x,int y,int rt)
{
    int ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans += query(rt,1,N,id[top[x]],id[x]);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans += query(rt,1,N,id[x],id[y]);
    return ans;
}
int sum(int x,int y,int rt)
{
    int ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans = Max(ans,Query(rt,1,N,id[top[x]],id[x]));
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans = Max(ans,Query(rt,1,N,id[x],id[y]));
    return ans;
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,m,a,b,x,y;
    n = read();m = read();
    char opt[5];
    for(int i = 1;i<=n;++i){
        arr[i] = read();belong[i] = read();
    }
    init();
    for(int i = 1;i<n;++i)
    {
        a = read();b= read();
        add(a,b);add(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    for(int i = 1;i<=n;++i)
    {
        update(root[belong[i]],1,N,id[i],arr[i]);
    }
    for(int i = 1;i<=m;++i)
    {
        scanf("%s",opt);
        x = read();y =read();
        if(opt[0]=='Q')
        {
            if(opt[1]=='S')
            {
                printf("%d\n",Sum(x,y,root[belong[x]]));
            }
            else
            {
                printf("%d\n",sum(x,y,root[belong[x]]));
            }
        }
        else
        {
            if(opt[1]=='C')
            {
                int last = belong[x];
                update(root[last],1,N,id[x],0);
                belong[x] = y;
                update(root[y],1,N,id[x],arr[x]);
            }
            else
            {
                arr[x] = y;
                update(root[belong[x]],1,N,id[x],y);
            }
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

HDU6547
女生賽的題 寫完隊友問我有沒有樹鏈剖分板子 臉都沒了 作爲數據結構選手 西安E都不懂點和點之間的最短路是什麼 隊友這樣問 小菜雞決定好好學下樹鏈剖分
這題能讀題到碼完提交AC僅用14分鐘 希望今年區域賽小菜雞也能這樣

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100025;
int n,p[MAX_N],eid,arr[MAX_N],cnt,top[MAX_N],Rank[MAX_N],id[MAX_N],sz[MAX_N],son[MAX_N],fa[MAX_N],depth[MAX_N],maxx[MAX_N<<2];
ll s[MAX_N<<2];
void init()
{
    memset(p,-1,sizeof(p));
    eid = 0;
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
int Max(int a,int b) {return a > b?a:b;}
void up(int rt)
{
    s[rt] = s[rt<<1]+s[rt<<1|1];
    maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        maxx[rt] = s[rt] = arr[Rank[l]];
        return ;
    }
    int mid =(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void update(int rt,int l,int r,int x,int y)
{
    if(maxx[rt]==1) return;
    if(l==r) {maxx[rt] = sqrt(maxx[rt]);s[rt] = maxx[rt];return;}
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) update(rt<<1,l,mid,x,y);
    else update(rt<<1,l,mid,x,y),update(rt<<1|1,mid+1,r,x,y);
    up(rt);
}
ll query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y) return s[rt];
    int mid  = (l+r)>>1;
    if(x>mid) return query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid) return query(rt<<1,l,mid,x,y);
    else return query(rt<<1,l,mid,x,y)+query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{
    fa[x] = fath;
    depth[x] = depth[fath]+1;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int  v =e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt ] = u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v =e[i].v;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
ll sum(int x,int y)
{
    ll ans = 0;
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        ans += query(1,1,n,id[top[x]],id[x]);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    ans+=query(1,1,n,id[x],id[y]);
    return ans;
}
void updates(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x]);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update(1,1,n,id[x],id[y]);
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int a,b,m,opt,x,y;
    n  =read();m = read();
    init();
    for(int i = 1;i<=n;++i) arr[i] = read();
    for(int i = 1;i<n;++i)
    {
        a = read();b = read();
        add(a,b);add(b,a);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    for(int i = 1;i<=m;++i)
    {
        opt = read();x=read();y=read();
        if(opt==0)
        {
            updates(x,y);
        }
        else
        {
            printf("%lld\n",sum(x,y));
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

西安邀請賽E
這道題線段樹版本有道升級版本
FZU2105
然後小菜雞ljq很容易就想到線段樹怎麼做
然後跟隊友說 這題能出
等下 他問點和點之間的最短路
woc 點和點之間的最短路是什麼啊 猝

拆位 維護區間1的個數 奇數表示存在 偶數表示不存在

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;


#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 100025;
int ans,n,p[MAX_N],eid,cnt,id[MAX_N],Rank[MAX_N],arr[MAX_N],sz[MAX_N],fa[MAX_N],son[MAX_N],s[MAX_N<<2][31],col[MAX_N<<2][31],depth[MAX_N],top[MAX_N];
void init()
{
    eid = 0;
    memset(p,-1,sizeof(p));
}
struct edge
{
    int v,next;
}e[MAX_N<<1];
void add(int u,int v)
{
    e[eid].v = v;
    e[eid].next = p[u];
    p[u] = eid++;
}
void up(int rt)
{
    for(int i = 0;i<30;++i)
    {
        s[rt][i] = s[rt<<1][i] + s[rt<<1|1][i];
    }
}
void build(int rt,int l,int r)
{
    for(int i = 0;i<30;++i) col[rt][i] = -1;
    if(l==r)
    {
        for(int i = 0;i<30;++i)
        {
            if((1<<i)&arr[Rank[l]]) s[rt][i] = 1;
            else s[rt][i] = 0;
        }
        return ;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
void down(int rt,int l,int r)
{
    int mid = (l+r)>>1;
    for(int i = 0;i<30;++i)
    {
        if(col[rt][i]!=-1)
        {
            col[rt<<1|1][i] = col[rt<<1][i] = col[rt][i];
            if(col[rt][i]==1)
            {
                s[rt<<1][i] = mid-l+1;
                s[rt<<1|1][i] = r-mid;
            }
            else
            {
                s[rt<<1][i] = 0;
                s[rt<<1|1][i] = 0;
            }
            col[rt][i] = -1;
        }
    }
}
void update(int rt,int l,int r,int x,int y,int v,int flag)
{
    if(x<=l&&r<=y)
    {
        if(flag==1)
        {
            for(int i = 0;i<30;++i)
            {
                if((1<<i)&v)
                {
                    col[rt][i] = 1;
                    s[rt][i] = r-l+1;
                }
            }
        }
        else
        {
            for(int i = 0;i<30;++i)
            {
                if(!((1<<i)&v))
                {
                    col[rt][i] = 0;
                    s[rt][i] = 0;
                }
            }
        }
        return;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid) update(rt<<1|1,mid+1,r,x,y,v,flag);
    else if(y<=mid) update(rt<<1,l,mid,x,y,v,flag);
    else update(rt<<1,l,mid,x,y,v,flag),update(rt<<1|1,mid+1,r,x,y,v,flag);
    up(rt);
}
void query(int rt,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)
    {
        for(int i = 0;i<30;++i)
        {
            if(s[rt][i]&1) ans^=(1<<i);
        }
        return;
    }
    down(rt,l,r);
    int mid = (l+r)>>1;
    if(x>mid)  query(rt<<1|1,mid+1,r,x,y);
    else if(y<=mid)  query(rt<<1,l,mid,x,y);
    else  query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y);
}
void dfs1(int x,int fath)
{
    fa[x] = fath;
    depth[x] = depth[fath]+1;
    sz[x] = 1;
    for(int i = p[x];i+1;i=e[i].next)
    {
        int v = e[i].v;
        if(v==fath) continue;
        dfs1(v,x);
        sz[x]+=sz[v];
        if(sz[son[x]]<sz[v]) son[x] = v;
    }
}
void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    Rank[cnt] = u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i = p[u];i+1;i=e[i].next)
    {
        int v  =e[i].v;
        if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
    }
}
void sum(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        query(1,1,n,id[top[x]],id[x]);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    query(1,1,n,id[x],id[y]);
}
void updates(int x,int y,int c,int flag)
{
    while(top[x]!=top[y])
    {
        if(depth[top[x]]<depth[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],c,flag);
        x = fa[top[x]];
    }
    if(id[x]>id[y]) swap(x,y);
    update(1,1,n,id[x],id[y],c,flag);
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int m,x,y,opt;
    n = read();m = read();
    for(int i = 1;i<=n;++i) arr[i] = read();
    init();
    for(int i = 1;i<n;++i)
    {
        x = read();y=read();
        add(x,y);add(y,x);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    for(int i = 1;i<=n;++i)
    {
        opt = read();x=read();y=read();
        if(opt==1)
        {
            updates(1,x,y,1);
        }
        else if(opt==2)
        {
            updates(1,x,y,2);
        }
        else
        {
            ans = 0;
            sum(1,x);
            if(ans!=y) printf("YES\n");
            else printf("NO\n");
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章