BZOJ: 2819 Nim

二次联通门 : BZOJ: 2819 Nim

头痛的要死,果然还是写这种无脑题比较好

/*
    BZOJ: 2819 Nim

    链剖 + 线段树

    偷懒没写手工栈,特判了一下链的情况

*/
#include <cstdio>
#include <iostream>
#include <cstdlib>
#define Max 500005
#define rg register
inline void read (int &n)
{
    rg char c = getchar ();
    for (n = 0; !isdigit (c); c = getchar ());
    for (; isdigit (c); n = n * 10 + c - '0', c = getchar ());
}
int _n[Max << 1], _v[Max << 1], list[Max], EC, key[Max];
int f[Max], up[Max], s[Max], d[Max], id[Max], son[Max], tk[Max];
void Dfs_1 (int n, int F)
{
    f[n] = F, d[n] = d[F] + 1, s[n] = 1;
    for (rg int i = list[n]; i; i = _n[i])
        if (_v[i] != F)
        {
            Dfs_1 (_v[i], n), s[n] += s[_v[i]];
            if (s[son[n]] < s[_v[i]]) son[n] = _v[i];
        }
}
int TC;
void Dfs_2 (int n, int C)
{
    id[n] = ++ TC, tk[TC] = key[n], up[n] = C;        
    if (son[n]) Dfs_2 (son[n], C); else return ;
    for (rg int i = list[n]; i; i = _n[i])
        if (_v[i] != son[n] && _v[i] != f[n]) Dfs_2 (_v[i], _v[i]);
}

namespace seg
{
    int L[Max << 2], R[Max << 2], key[Max << 2];

    void Build (int n, int l, int r)
    {
        L[n] = l, R[n] = r;
        if (l == r) { key[n] = tk[l]; return ; }
        int m = l + r >> 1;
        Build (n << 1, l, m), Build (n << 1 | 1, m + 1, r);
        key[n] = key[n << 1] ^ key[n << 1 | 1];
    }

    void Modi (int n, int p, int k)
    {
        if (L[n] == R[n]) { key[n] = k; return; }
        int m = L[n] + R[n] >> 1;
        if (p <= m) Modi (n << 1, p, k); else Modi (n << 1 | 1, p, k);
        key[n] = key[n << 1] ^ key[n << 1 | 1];
    }

    int Query (int n, int l, int r)
    {
        if (l <= L[n] && R[n] <= r) return key[n];
        int m = L[n] + R[n] >> 1, ls = n << 1, rs = n << 1 | 1, a = -1;
        if (l <= m) a = Query (ls, l, r); 
        if (r > m) 
        {
            if (a != -1) a ^= Query (rs, l, r);
            else a = Query (rs, l, r);
        }
        return a;
    }
}
int in[Max];
inline void In (int u, int v)
{ _v[++ EC] = v, _n[EC] = list[u], list[u] = EC, ++ in[v]; }

inline bool Ask (int x, int y)
{
    int res = -1;
    for (; up[x] != up[y]; x = f[up[x]])
    {
        if (d[up[x]] < d[up[y]]) std :: swap (x, y);
        if (res == -1) res = seg :: Query (1, id[up[x]], id[x]);
        else res ^= seg :: Query (1, id[up[x]], id[x]);
    }
    if (d[x] > d[y]) std :: swap (x, y);
    if (res == -1) res = seg :: Query (1, id[x], id[y]);
    else res ^= seg :: Query (1, id[x], id[y]);
    return res != 0;
}
int pos[Max];
int main (int argc, char *argv[])
{
    int N, M, x, y; read (N); rg int i; int f1 = 0, f2 = 0;
    for (i = 1; i <= N; ++ i) read (key[i]);
    for (i = 1; i < N; ++ i)
        read (x), read (y), In (x, y), In (y, x);        

    int t = 0, pre; 
    for (i = 1; i <= N; ++ i)
        if (in[i] == 2) ++ f2; 
        else if (in[i] == 1) ++ f1, pos[++ t] = i;
    read (M); 
    char type[4];
    if (f1 + f2 == N) 
    {
        int n = pos[1];
        id[n] = ++ TC, pre = 0, tk[TC] = key[n];
        
        for (; n != pos[2]; )
            for (i = list[n]; i; i = _n[i])
                if (_v[i] != pre)
                { id[_v[i]] = ++ TC, tk[TC] = key[_v[i]], pre = n, n = _v[i]; break; }
                    
        id[n] = ++ TC, tk[TC] = key[n];

        seg :: Build (1, 1, N);    
        
        for (; M; -- M)
        {
            scanf ("%s", type),    read (x), read (y);
            if (type[0] == 'Q')
            {
                if (id[x] > id[y]) std :: swap (x, y);
                puts (seg :: Query (1, id[x], id[y]) == 0 ? "No" : "Yes");
            }
            else seg :: Modi (1, id[x], y);
        }
        return 0;
    }

    Dfs_1 (1, 0), Dfs_2 (1, 1), seg :: Build (1, 1, N);
    for (; M; -- M)
    {
        scanf ("%s", type); read (x), read (y);
        if (type[0] == 'Q')
            puts (Ask (x, y) ? "Yes" : "No");
        else seg :: Modi (1, id[x], y);
    }    

    return 0;
}