您的位置:首页 > 其它

HDU 5274 Dylans loves tree(DFS序+线段树+LCA离线查询模板+手动扩大内存)

2015-07-14 11:06 330 查看

题意:

Dylans有一棵N个点的树。每个点有点权。树上节点标号为1∼N。

他得到了Q个询问,形式如下:

①0 x y:把第x个点的点权修改为y。

②1 x y:对于x∼y路径上的每一种点权,是否都出现偶数次?

保证每次询问的路径上最多只有一种点权的出现次数是奇数次。

1≤N,Q≤100000, 点权A[i]∈N,且都 ≤100000

解析:

这题比较难啊,参考了一下网络上面的题解。


如果一个数组, 只有一个数字出现奇数次, 有什么比较好的方法 快速找出这个数字?

答:因为两个相同的数异或和等于0,所以把所有的数字异或在一起,异或和就是,出现的奇数数字。

那么能想到用线段树来维护异或和的方法,来解决这一题。


有一种经典的将树上的点转化成序列的方法,我们用dfs遍历这棵树,那么对于一个节点,他一点比他的子树即子节点先访问到,且当他的最后一个子节点的所有子树也都访问完时,这中间访问的节点一定都是他的子树。那么我们可以在访问时做一下记录,每个点首先被访问的index和结束时的index,那么这中间的便是他的子树。


转换成序列之后就能利用线段树进行维护了。


具体做法就是:

先用dfs一遍求出,到每个点的dfs序,记录下该dfs序,以便之后用dfs维护。

然后构建一个线段树,来表示每个区间的异或和。

然后修改(u,x)(u,x)的话,就直接利用线段树进行区间更新,注意修改的值为 val[u]⊕xval[u] ⊕ x,因为val[u]val[u]和子树异或过了,如果想要修改u并更新子树,就必须先消去val[u]val[u],然后再异或上x。

如果查询(u,v)(u,v)的话,就ans=query(st[u],ed[u])⊕query(st[v],ed[v])⊕val[LCA(u,v)]ans = query(st[u], ed[u]) ⊕ query(st[v], ed[v]) ⊕ val[LCA(u,v)]

注意

这题有坑的地方就是点权可能为0,处理方法是先把所以的点权都加上1,最后再减1。

mymy codecode

[code]#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#define ls o<<1
#define rs o<<1|1
#define lson o<<1,L,M
#define rson o<<1|1,M+1,R
using namespace std;
typedef long long ll;
const int N = 1e5+10;

int n,q;

int val
;
vector<int> G
;

int st
, ed
;

namespace LCA {
    int first
, node[N*2], deep[N*2];
    struct ST {
        int dp[N*2][20];

        void init(int n) {
            for(int i = 1; i <= n; i++) dp[i][0] = i;
            for(int k = 1; (1 << k) <= n; k++) {
                for(int i = 1; i <= n-(1<<k)+1; i++) {
                    int a = dp[i][k-1];
                    int b = dp[i+(1<<(k-1))][k-1];
                    dp[i][k] = (deep[a] < deep[b]) ? a : b;
                }
            }
        }

        int query(int L, int R) {
            int len = (R-L+1), k = 0;
            while((1<<(k+1)) <= len) k++;
            int a = dp[L][k], b = dp[R-(1<<k)+1][k];
            return (deep[a] < deep[b]) ? a : b;
        }
    } table;

    int clock, index;
    void dfs(int u, int pre, int de) {
        st[u] = ++index;
        node[++clock] = u;
        deep[clock] = de;
        first[u] = clock;
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if(v == pre) continue;
            dfs(v, u, de+1);
            node[++clock] = u;
            deep[clock] = de;
        }
        ed[u] = index;
    }

    void init(int n) {
        clock = 0;
        index = 0;
        dfs(1, -1, 0);
        table.init(2*n-1);
    }

    int lca(int u, int v) {
        int L = first[u], R = first[v];
        if(L > R) swap(L, R);
        return node[table.query(L, R)];
    }
}

struct Node{
    int val, set;
} node[N<<2];

inline void pushUp(Node& fa, Node& Ls, Node& Rs){
    fa.val = (Ls.val ^ Rs.val);
}

inline void pushDown(Node& fa, Node& Ls, Node& Rs){
    if (fa.set) {
        Ls.val ^= fa.set; Ls.set ^= fa.set;
        Rs.val ^= fa.set; Rs.set ^= fa.set;
        fa.set = 0;
    }
}

void modify(int o, int L, int R, int ql, int qr, int delta){
    if (ql <= L && R <= qr) {
        node[o].val ^= delta;
        node[o].set ^= delta;
        return;
    }
    int M = (L+R)/2;
    pushDown(node[o], node[ls], node[rs]);
    if (ql <= M) modify(lson, ql, qr, delta);
    if (qr > M) modify(rson, ql, qr, delta);
    pushUp(node[o], node[ls], node[rs]);
}

int query(int o, int L, int R,int ql, int qr){
    if(ql<=L && R<=qr){
        return node[o].val;
    }
    int M = (L+R)/2;
    pushDown(node[o], node[ls], node[rs]);
    int ret = 0;
    if(qr <= M) ret ^= query(lson,ql,qr);
    if(ql > M) ret ^= query(rson,ql,qr);
    return ret;
}

void addEdge(int u, int v) {
    G[u].push_back(v);
}

int MAIN() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) G[i].clear();

        int u, v;
        for(int i=1;i<=n-1;i++){
            scanf("%d%d",&u,&v);
            addEdge(u, v);
            addEdge(v, u);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
            val[i]++;
        }

        LCA::init(n);
        memset(node,0,sizeof(node));
        for(int i=1;i<=n;i++)
            modify(1,1,n,st[i],ed[i],val[i]);

        while(q--) {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(a == 0) {
                c++;
                modify(1,1,n,st[b],ed[b],val[b]^c);
                val[b] = c;
            }else {
                int wt1 = query(1,1,n,st[b],st[b]);
                int wt2 = query(1,1,n,st[c],st[c]);
                int wt3 = val[LCA::lca(b,c)];
                int ans = wt1^wt2^wt3;
                printf("%d\n",ans-1);
            }
        }
    }
    return 0;
}

const int main_stack = 16;
char my_stack[128<<20];

int main() {
    __asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory");
    __asm__("movl %%eax, %%esp;\n"::"a"(my_stack + sizeof(my_stack) - main_stack):"%esp");
    MAIN();
    __asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp");
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: