树链刨分(待修改)

没调出来,明天搞。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = 1 << 30;
const int N = 100005;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
struct edge
{
    int nxt,r;
} e[2 * N];
int n,m,r,cnt;
int a[N],lst[N],p;
int f[N],d[N],siz[N],son[N],rk[N];
int top[N],id[N],tree[4 * N];
int lazy[N],len = 0;

void add(int x,int y)
{
    e[++len].nxt = lst[x];
    e[len].r = y;
    lst[x] = len;
}

void dfs1(int u,int fa,int depth)
{
    f[u] = fa;
    d[u] = depth;
    siz[u] = 1;
    for(int k = lst[u];k;k = e[k].nxt)
    {
        int y = e[k].r;
        if(y == fa)
            continue;
        dfs1(y,u,depth + 1);
        siz[u] += siz[y];
        if(siz[y] > siz[son[u]])
        {
            son[u] = y;
        }
    }
}

void dfs2(int u,int t)
{
    top[u] = t;
    id[u] = ++cnt;
    rk[cnt] = u;
    if(!son[u])
        return;
    dfs2(son[u],t);
    for(int k = lst[u];k;k = e[k].nxt)
    {
        int y = e[k].r;
        if(y != son[u] && y != f[u])
            dfs2(y,y);
    }
}

void push_down(int o,int l,int r)
{
    lazy[o << 1] += lazy[o];
    lazy[o << 1 | 1] += lazy[o];
    int len = (r - l + 1);
    tree[o << 1] += lazy[o] * (len - len >> 1);
    tree[o << 1 | 1] += lazy[o] * (len >> 1);
    a[o << 1] %= p;
    a[o << 1 | 1] %= p;
    lazy[o] = 0;
}

void build(int o,int l,int r)
{
    if(l == r)
    {
        tree[o] = a[rk[l]];
        tree[o] %= p; 
        return;
    }
    int mid = (l + r) >> 1;
    build(o << 1,l,mid);
    build(o << 1 | 1,mid + 1,r);
    push_down(o,l,r);
}

void up_num(int o,int l,int r,int x,int y,int w)
{
    if(l == x && r == y)
    {
        tree[o] += w * (l - r + 1);
        lazy[o] += w;
        return;
    }
    int mid = (l + r) >> 1;
    push_down(o,l,r);
    if(mid < x)
        up_num(o << 1 | 1,mid + 1,r,x,y,w);
    else if(mid >= y)
        up_num(o << 1,l,mid,x,y,w);
    else
    {
        up_num(o << 1,l,mid,x,mid,w);
        up_num(o << 1 | 1,mid + 1,r,mid + 1,y,w);
    }
    tree[o] = tree[o << 1] + tree[o << 1 | 1];
    tree[o] %= p;
}

int query(int o,int l,int r,int x,int y)
{
    if(l == r && x == y)
    {
        return tree[o];
    }
    int mid = (l + r) >> 1;
    if(mid >= y)
        return query(o << 1,l,mid,x,y);
    else if(mid < x)
        return query(o << 1 | 1,mid + 1,r,x,y);
    else
    {
        query(o << 1,l,mid,x,mid);
        query(o << 1 | 1,mid + 1,r,mid + 1,y);
        push_down(o,l,r);
        return tree[o];
    }
}

int sum_mak(int x,int y)
{
    int ans = 0,fx = top[x],fy = top[y];
    while(fx != fy)
    {
        if(d[fx] >= d[fy])
        {
            ans += query(1,1,n,id[fx],id[x]);
            x = f[fx];
        }
        else
        {
            ans += query(1,1,n,id[fy],id[y]);
            y = f[fy];
        }
        fx = top[x];
        fy = top[y];
    } 
    if(id[x] <= id[y])
        ans += query(1,1,n,id[x],id[y]);
    else
        ans += query(1,1,n,id[y],id[x]);
    return ans;
}

void updates(int x,int y,int c)
{
    int fx = top[x],fy = top[y];
    while(fx != fy)
    {
        if(d[fx] >= d[fy])
        {
            up_num(1,1,n,id[fx],id[x],c);
            x = f[fx];
        }
        else
        {
            up_num(1,1,n,id[fy],id[y],c);
            y = f[fy];
        }
        fx = top[x];
        fy = top[y];
    }
    if(id[x] <= id[y])
        up_num(1,1,n,id[x],id[y],c);
    else
        up_num(1,1,n,id[y],id[x],c);
}



int main()
{
    read(n);read(m);read(r);read(p);
    duke(i,1,n)
    read(a[i]);
    duke(i,1,n - 1)
    {
        int x,y;
        read(x);read(y);
        add(x,y);
        add(y,x);
    }
    cnt = 0;
    dfs1(r,0,1);
    dfs2(r,r);
    cnt = 0;
    build(1,1,n);
    duke(i,1,m)
    {
        int op,x,y,z;
        read(op);
        if(op == 1)
        {
            read(x);read(y);read(z);
            updates(x,y,z);
        }
        else if(op == 2)
        {
            read(x);read(y);
            printf("%d
",sum_mak(x,y));
        }
        else if(op == 3)
        {
            read(x);read(z); 
//            cout<<x<<endl;
            up_num(1,1,n,id[x],id[x] + siz[x] - 1,z);
        }
        else
        {
            read(x);
            printf("%d
",query(1,1,n,id[x],id[x] + siz[x] - 1));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/DukeLv/p/9588184.html