码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

时间:2015-07-22 13:19:22      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:

Problem Description
Dylans is given a tree with N技术分享 nodes.

All nodes have a value A[i]技术分享.Nodes on tree is numbered by 1N技术分享.

Then he is given Q技术分享 questions like that:

0 x y技术分享:change node x技术分享技术分享s技术分享 value to y技术分享

1 x y技术分享:For all the value in the path from x技术分享 to y技术分享,do they all appear even times?

For each ② question,it guarantees that there is at most one value that appears odd times on the path.

1N,Q100000技术分享, the value A[i]N技术分享 and A[i]100000技术分享
 

Input
In the first line there is a test number T技术分享.
(T3技术分享 and there is at most one testcase that N>1000技术分享)

For each testcase:

In the first line there are two numbers N技术分享 and Q技术分享.

Then in the next N?1技术分享 lines there are pairs of (X,Y)技术分享 that stand for a road from x技术分享 to y技术分享.

Then in the next line there are N技术分享 numbers A技术分享1技术分享..A技术分享N技术分享技术分享 stand for value.

In the next Q技术分享 lines there are three numbers(opt,x,y)技术分享.
 

Output
For each question ② in each testcase,if the value all appear even times output "-1",otherwise output the value that appears odd times.
 

Sample Input
1 3 2 1 2 2 3 1 1 1 1 1 2 1 1 3
 

Sample Output
-1 1
Hint
If you want to hack someone,N and Q in your testdata must smaller than 10000,and you shouldn‘t print any space in each end of the line.
 

Source
 


大致题意:

一棵树1e5节点的树,有1e5次两种操作,修改某点的权值,询问两点间的路径上的每个权值是否都是偶数个,若不是输出奇数个的权值大小,保证询问的路径上最多只有一个权值是奇数个


思路:

方法1.维护每个点到根的异或,然后查询就是xor[u]^xor[v]^LCA(u,v)

更新操作:更新某个点显然此点的子树的xor到根的异或都会更新,所以用dfs记录进入节点和退出节点的时间戳,把时间戳作为节点映射到线段树上(所以个数是数节点的两倍),然后成段更新进入此节点到退出此节点的时间戳的区间即可

复杂度是nlogn

方法2:

正面上,询问就是两个点间的路径的异或,即树链剖分

复杂度n*logn*logn


方法一:

#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;

const int N = 1e5+100;
int n,Q;
int indx;
struct Edge
{
    int v,nxt;
    Edge(){}
    Edge(int v,int nxt):v(v),nxt(nxt){}
}es[N<<1];
int head[N],ecnt;
inline void add_edge(int v,int u)
{
    es[ecnt] = Edge(v,head[u]);
    head[u] = ecnt++;
    es[ecnt] = Edge(u,head[v]);
    head[v] = ecnt++;
}
int val[N];
//....................................
#define root 1,indx,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int XOR[N<<2];
inline void pushup(int rt)
{
    XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
}
void update(int pos,int x,int l,int r,int rt)
{
    if(l == r)
    {
        XOR[rt] ^= x;
        return ;
    }
    int m = (l+r)>>1;
    if(pos <= m) update(pos,x,lson);
    else update(pos,x,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L <= l && r <= R) return XOR[rt];
    int m = (l+r)>>1;
    int ans = 0;
    if(L <= m) ans ^= query(L,R,lson);
    if(R > m) ans ^= query(L,R,rson);
    return ans;
}
//.................................
int dep[N],hvyson[N],sz[N],fa[N];
void dfs1(int u)
{
    dep[u] = dep[fa[u]]+1;
    hvyson[u] = 0,sz[u] = 1;
    for(int i = head[u];~i;i = es[i].nxt)
    {
        int v = es[i].v;
        if(v == fa[u]) continue;
        fa[v] = u;
        dfs1(v);
        sz[u] += sz[v];
        if(sz[v] > sz[hvyson[u]]) hvyson[u] = v;
    }
}
int tp[N],tid[N];
void dfs2(int u,int ance)
{
    tid[u] = ++indx;
    tp[u] = ance;
    if(hvyson[u]) dfs2(hvyson[u],ance);
    for(int i = head[u];~i;i = es[i].nxt)
    {
        int v = es[i].v;
        if(v == fa[u]) continue;
        if(v != hvyson[u])dfs2(v,v);
    }
}
int ask(int u,int v)
{
    int anceu = tp[u],ancev = tp[v];
    int ans = 0;
    while(anceu != ancev)
    {
        if(dep[anceu] < dep[ancev]) swap(anceu,ancev),swap(u,v);
        ans ^= query(tid[anceu],tid[u],root);
        u = fa[anceu];
        anceu = tp[u];
    }
    if(u == v) return ans ^= val[u];
    if(dep[u] < dep[v]) return ans ^= query(tid[u],tid[v],root);
    else return ans ^= query(tid[v],tid[u],root);
}
//..................................
void ini()
{
    ecnt = indx = 0;
    memset(head,-1,sizeof(head));
    memset(XOR,0,sizeof(XOR));
}
int main()
{

    int T;
    scanf("%d",&T);
    while(T--)
    {
        ini();
        scanf("%d%d",&n,&Q);
        REP(i,n-1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        REP(i,n) scanf("%d",&val[i]),val[i]++;
        dfs1(1);
        dfs2(1,1);
        REP(i,n) update(tid[i],val[i],root);
        REP(i,Q)
        {
            int op;
            scanf("%d",&op);
            if(op == 0)
            {
                int u,x;
                scanf("%d%d",&u,&x);x++;
                update(tid[u],val[u]^x,root);
                val[u] = x;
            }
            else
            {
                int u,v;
                scanf("%d%d",&u,&v);
                printf("%d\n",ask(u,v)-1);
            }
        }
    }
}


方法二:

//312MS 21660K 4306 B C++
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;

const int N = 1e5+100;
int n,Q;
struct Edge
{
    int v,nxt;
    Edge(){}
    Edge(int v,int nxt) : v(v),nxt(nxt){}
}es[N*2];
int ecnt,head[N];
inline void add_edge(int u,int v)
{
    es[ecnt] = Edge(v,head[u]);
    head[u] = ecnt++;
    es[ecnt] = Edge(u,head[v]);
    head[v] = ecnt++;
}
int val[N];
//...................................

int indx,st[N],ed[N],vs[N<<1];
int dp[N];
void dfs(int u,int fa)
{
    dp[u] = dp[fa]^val[u];
    st[u] = ++indx;
    vs[indx] = u;
    for(int i = head[u];~i;i = es[i].nxt)
    {
        int v = es[i].v;
        if(v == fa) continue;
        dfs(v,u);
    }
    ed[u] = ++indx;
    vs[indx] = u;
}


//...............................

int dep[N];
bool vis[N];
int pa[N][20];
void bfs()
{
    queue<int>q;
    q.push(1);
    pa[1][0]=1;
    vis[1]=1;
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1];
        for(int i=head[u];~i;i=es[i].nxt)
        {
            int v=es[i].v;
            if(vis[v]==0)
            {
                vis[v]=1;
                pa[v][0]=u;
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
}

int LCA(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    for(int det=dep[v]-dep[u],i=0;det;i++,det>>=1)
        if(det&1) v=pa[v][i];
    if(v==u) return v;
    for(int i=20-1;i>=0;i--)
        if(pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i];
    return pa[u][0];
}
//...............................
int XOR[(N<<1)<<2],col[(N<<1)<<2];
#define root 1,indx,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

inline void pushup(int rt)
{
    XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
}
inline void pushdown(int rt)
{
    if(col[rt] == 0) return ;
    col[rt<<1] ^= col[rt];
    col[rt<<1|1] ^= col[rt];
    XOR[rt<<1] ^= col[rt];
    XOR[rt<<1|1] ^= col[rt];
    col[rt] = 0;
}
void build(int l,int r,int rt)
{
    if(l == r)
    {
        XOR[rt] = dp[vs[l]];
        col[rt] = 0;
        return ;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}

void update(int L,int R,int x,int l,int r,int rt)
{
    if(L <= l && r <= R)
    {
        XOR[rt] ^= x;
        col[rt] ^= x;
        return ;
    }
    pushdown(rt);
    int m = (l+r)>>1;
    if(L <= m) update(L,R,x,lson);
    if(R > m) update(L,R,x,rson);
    pushup(rt);
}
int query(int pos,int l,int r,int rt)
{
    if(l == r) return XOR[rt];
    pushdown(rt);
    int m = (l+r)>>1;
    if(pos <= m) return query(pos,lson);
    else return query(pos,rson);
}
//..............................
void ini()
{
    indx = ecnt = 0;
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ini();
        scanf("%d%d",&n,&Q);
        REP(i,n-1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add_edge(u,v);
        }
        REP(i,n) scanf("%d",&val[i]),val[i]++;
        dfs(1,0);
        bfs();
        build(root);
        while(Q--)
        {
            int op;
            scanf("%d",&op);
            if(op == 0)
            {
                int u,x;
                scanf("%d%d",&u,&x);
                x++;
                update(st[u],ed[u],val[u]^x,root);
                val[u] = x;
            }
            else
            {
                int u,v;
                scanf("%d%d",&u,&v);
                int ans = query(ed[u],root)^query(ed[v],root)^val[LCA(u,v)];
                printf("%d\n",ans-1);
            }
        }
    }
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

标签:

原文地址:http://blog.csdn.net/kalilili/article/details/46999415

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!