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

来源:互联网 发布:仓位在线软件 编辑:程序博客网 时间:2024/06/06 09:43

题意:

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)的话,就直接利用线段树进行区间更新,注意修改的值为 val[u]x,因为val[u]和子树异或过了,如果想要修改u并更新子树,就必须先消去val[u],然后再异或上x。
如果查询(u,v)的话,就ans=query(st[u],ed[u])query(st[v],ed[v])val[LCA(u,v)]

注意

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

my 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,Rusing namespace std;typedef long long ll;const int N = 1e5+10;int n,q;int val[N];vector<int> G[N];int st[N], ed[N];namespace LCA {    int first[N], 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;}
0 0
原创粉丝点击