Cow Land (树链剖分)

测试链接

题面:

Cow Land is a special amusement park for cows, where they roam around, eat delicious grass, and visit different cow attractions (the roller cowster is particularly popular).

There are a total of N different attractions (2≤N≤1e5 ). Certain pairs of attractions are connected by pathways, N-1 in total, in such a way that there is a unique route consisting of various pathways between any two attractions. Each attraction?ii?has an integer enjoyment value ei, which can change over the course of a day, since some attractions are more appealing in the morning and others later in the afternoon.

A cow that travels from attraction i to attraction j gets to experience all the attractions on the route from i to j. Curiously, the total enjoyment value of this entire route is given by the bitwise XOR of all the enjoyment values along the route, including those of attractions i and j.

Please help the cows determine the enjoyment values of the routes they plan to use during their next trip to Cow Land.

INPUT
The first line of input contains N and a number of queries Q (1≤Q≤1e5). The next line contains e1…eN (0≤ei≤1e9). The next N lines each describe a pathway in terms of two integer attraction IDs a and b (both in the range 1…N). Finally, the last Q?lines each describe either an update to one of the ei values or a query for the enjoyment of a route. A line of the form “1 i v” indicates that ei should be updated to value v, and a line of the form “2 i j” is a query for the enjoyment of the route connecting attractions i and j. In test data worth at most 50% of points, there will be no changes to the values of the attractions.

OUTPUT
For each query of the form “2 i j“, print on a single line the enjoyment of the route from i to j.

1 2 4 8 16
1 2
1 3
3 4
3 5
2 1 5
1 1 16
2 3 5
2 1 5
2 1 3

21
20
4
20



题意:

有一棵n个节点的树,每个节点有一个值。
有q个操作,操作分两种:
1 x y:修改节点x的值为y
2 x y:查询点x和点y之间路径上所有点的异或(包括这两个点)

思路:

树链剖分维护区间异或,修改是单点修改,查询是区间查询,都很基础。

参考代码:
#include<bits/stdc++.h>
using namespace std;

#define lson rt<<1
#define rson rt<<1|1

const int maxn=2e5+5;

int n,m;

int val[maxn],nxb[maxn];
struct node
{
    int u,v,nxt;
    node(){}
    node(int u,int v,int nxt):u(u),v(v),nxt(nxt){}
}edge[maxn<<2];
int cnt;
int head[maxn<<2];
int dep[maxn],fa[maxn],sonsize[maxn],hson[maxn],topfa[maxn];
int newval[maxn];
void addedge(int u,int v)
{
    edge[++cnt]=node(u,v,head[u]);
    head[u]=cnt;
}
int tree[maxn<<2],lazy[maxn<<2];

void bulid(int rt,int l,int r)
{
    if(l==r)
    {
        tree[rt]=newval[++cnt];
        return;
    }
    int mid=(l+r)>>1;
    bulid(lson,l,mid);
    bulid(rson,mid+1,r);
    tree[rt]=tree[lson]^tree[rson];
}

void update(int rt,int l,int r,int x,int y,int v)
{
    if(l==r&&l==x&&r==y)
    {
        tree[rt]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(y<=mid)update(lson,l,mid,x,y,v);
    else if(x>=mid+1)update(rson,mid+1,r,x,y,v);
    else update(lson,l,mid,x,mid,v),update(rson,mid+1,r,mid+1,y,v);
    tree[rt]=tree[lson]^tree[rson];
}

int query(int rt,int l,int r,int x,int y)
{
    if(l>=x&&r<=y)
    {
        return tree[rt];
    }
    int mid=(l+r)>>1;
    int ret=0;
    if(y<=mid)ret=query(lson,l,mid,x,y);
    else if(x>=mid+1)ret=query(rson,mid+1,r,x,y);
    else ret=(query(lson,l,mid,x,mid)^query(rson,mid+1,r,mid+1,y));
    return ret;
}

void dfs1(int u,int f,int deep)
{
    dep[u]=deep;
    fa[u]=f;
    sonsize[u]=1;
    hson[u]=0;
    int maxson=-1;
    for(int i=head[u];~i;i=edge[i].nxt)
    {
        int v=edge[i].v;
        if(v==f)continue;
        dfs1(v,u,deep+1);
        sonsize[u]+=sonsize[v];
        if(sonsize[v]>maxson)maxson=sonsize[v],hson[u]=v;
    }
}

void dfs2(int u,int topf)
{
    nxb[u]=++cnt;
    newval[cnt]=val[u];
    topfa[u]=topf;
    if(!hson[u])return;
    dfs2(hson[u],topf);
    for(int i=head[u];~i;i=edge[i].nxt)
    {
        int v=edge[i].v;
        if(v==fa[u]||v==hson[u])continue;
        dfs2(v,v);
    }
}

int sum_lian(int u,int v)
{
    int ret=0;
    while(topfa[u]!=topfa[v])
    {
        if(dep[topfa[u]]<dep[topfa[v]])swap(u,v);
        ret^=query(1,1,n,nxb[topfa[u]],nxb[u]);
        u=fa[topfa[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    ret=ret^query(1,1,n,nxb[u],nxb[v]);
    return ret;
}

void up_point(int u,int k){
    update(1,1,n,nxb[u],nxb[u],k);
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&val[i]);
    int x,y;
    cnt=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    cnt=0;
    dfs1(1,0,1);
    dfs2(1,1);
    cnt=0;
    bulid(1,1,n);
    int op;
    while(m--)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(op==1){
            up_point(x,y);
        }
        else {
            printf("%d\n",sum_lian(x,y));
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值