洛谷3690——树链剖分模板

给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。
0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。
1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。
2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
3:后接两个整数(x,y),代表将点x上的权值变成y。
输入输出格式
输入格式:
第1行两个整数,分别为n和m,代表点数和操作数。
第2行到第n+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第n+2行到第n+m+1行,每行三个整数,分别代表操作类型和操作所需的量。
输出格式:
对于每一个0号操作,你须输出x到y的路径上点权的xor和。
输入输出样例
输入样例#1:
3 3
1
2
3
1 1 2
0 1 2
0 1 1
输出样例#1:
3
1
说明
数据范围: 1N1 \leq N,M3M \leq 3 105\cdot {10}^5

树剖板子题

不过细节码量还是有点大

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)/2)
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
int sum[400005],mark[400005],n,m,r,mod,adj[200005],nxt[200005],to[200004],cnt;
int fa[200005],son[200005],id[200005],dep[200005],siz[200005],top[200005],w[200005],val[200005];
inline void addedge(int u,int v){
    nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u;
}
int pushup(int rt)
{
    sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % mod;
}
inline void pushdown(int u,int len)
{
    if(mark[u])
    {
        mark[u*2]+=mark[u];
        mark[(u*2)+1]+=mark[u];
        sum[u*2]+=mark[u]*(len-(len>>1));
        sum[u*2]%=mod;
        sum[(u*2)+1]+=mark[u]*(len>>1);
        sum[(u*2)+1]%=mod;
        mark[u]=0;
    }
}
inline void buildtree(int u,int l,int r,int dep)
{
    if(l==r)
    {
            sum[u]=val[l];
            sum[u]%=mod;
            return ;
    }
    buildtree(u*2,l,mid,dep+1);
    buildtree((u*2)+1,mid+1,r,dep+1);
    pushup(u);
}
void update(int u,int l,int r,int L, int R, int c)
{
    if (L <= l && r <= R)
    {
        mark[u] += c;
        sum[u] += c * (r - l + 1);
        sum[u] %= mod;
        return;
    }
    pushdown(u, r - l + 1);
    int m = (l + r) >> 1;
    if (L <= m)
        update(u*2,l,m,L, R, c);
    if (R > m)
        update((u*2)+1,m+1,r,L, R, c);
    pushup(u);
}
inline int query(int u,int l,int r,int st,int des)
{
    if(l>des||r<st) return 0;
    int ans=0;
    if(st<=l&&r<=des)
    {
        return sum[u];
    }
    pushdown(u,r-l+1);
    if(st<=mid)
    {
        ans+=query(u*2,l,mid,st,des);
        ans%=mod;
    }
    if(mid<des)
    {
        ans+=query((u*2)+1,mid+1,r,st,des);
        ans%=mod;
    }
    return ans;
}
inline void dfs1(int u,int f)
{
    dep[u]=dep[f]+1;
    fa[u]=f,siz[u]=1;
    int maxs=-1;
    for(int e=adj[u];e;e=nxt[e])
    {
        int v=to[e];
        if(v==f) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>maxs)
        {
            son[u]=v;
            maxs=siz[v];
        }
    }
}
inline void dfs2(int u,int topfa)
{
    id[u]=++cnt;
    val[cnt]=w[u];
    top[u]=topfa;
    if(!son[u]) return;
    dfs2(son[u],topfa);
    for(int e=adj[u];e;e=nxt[e])
    {
        int v=to[e];
        if(v==son[u]||v==fa[u]) continue;
        dfs2(v,v);
    }
}
inline void uprange(int x,int y,int k)
{
    k%=mod;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
 	}
 	if(dep[x]>dep[y]) swap(x,y);
 	update(1,1,n,id[x],id[y],k);
}
inline int qrange(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=query(1,1,n,id[top[x]],id[x]);
        ans%=mod;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=query(1,1,n,id[x],id[y]);
    return ans%mod;
}
inline void upson(int x,int k){
    update(1,1,n,id[x],id[x]+siz[x]-1,k);
}
inline int qson(int x)
{
    return query(1,1,n,id[x],id[x]+siz[x]-1);
}
int main()
{
    int u, v;
    n=read(),m=read(),r=read(),mod=read();
    for (int i = 1; i <= n; i++)
    w[i]=read();
    for (int i = 1; i <= n - 1; i++)
    {
        u=read(),v=read();
        addedge(u, v);
    }
    cnt=0;
    dfs1(r, 0);
    dfs2(r, r);
    buildtree(1, 1,n,1); 
    while (m--)
    {
        int op, x, y, z;
        op=read();
        if (op == 1)
        {
            x=read(),y=read(),z=read();
            uprange(x, y, z);
        }
        else if (op == 2)
        {
            x=read(),y=read();
            printf("%d\n", qrange(x, y));
        }
        else if (op == 3)
        {
            x=read(),z=read();
            upson(x, z);
        }
        else if (op == 4)
        {
            x=read(); 
            printf("%d\n", qson(x));
        }
    }
    return 0;
}
posted @ 2018-10-07 20:25  Stargazer_cykoi  阅读(82)  评论(0编辑  收藏  举报