落谷P3384树链剖分

题目地址

详解

#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<stdlib.h>
#include<time.h>
#include <iomanip>
#define lowbit(x) (x&(-x))
#define inf  0x7fffffff
#define linf 0x7fffffffffffffff
#define mem(x,y) memset(x,y,sizeof(x))
#define fup(i,x,y) for(int i=(x);i<=(y);i++)
#define fdn(i,x,y) for(int i=(x);i>=(y);i--)
#define sp(x) setprecision(x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define sc(n) scanf("%s",&n)
#define pf(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pff(x) printf("%lf\n",x)
#define N 100005
#define M 4000009

#define pi acos(-1)
#define eps 1e-2
//cout.setf(ios::fixed);
//freopen("out.txt","w",stdout);
using namespace std;
typedef long long  ll;
typedef double db;
const ll  mod=1e9+7;
struct node
{
    int go;
    node(int x):go(x){}
};
int f[N],d[N],siz[N],son[N],rk[N],top[N],id[N],a[N],n;
vector<node> edg[N];
int t[3*N],add[3*N],p;
void down(int r,int st,int ed)
{
    if(add[r])
    {
        add[r<<1]+=add[r];
        add[r<<1]%=p;
        add[r<<1|1]+=add[r];
        add[r<<1|1]%=p;
        int mid=(st+ed)>>1;
        t[r<<1]+=add[r]*(mid-st+1);
        t[r<<1|1]+=add[r]*(ed-mid);
        t[r<<1]%=p;
        t[r<<1|1]%=p;
        add[r]=0;
    }
}
void build(int r,int st,int ed)
{
    if(st==ed) t[r]=a[rk[st]];
    else
    {
        int mid=(st+ed)>>1;
        build(r<<1,st,mid);
        build(r<<1|1,mid+1,ed);
        t[r]=t[r<<1]+t[r<<1|1];
        t[r]%=p;
    }
}
void update(int r,int st,int ed,int x,int y,int z)
{
    if(st>y||ed<x) return ;
    if(st>=x&&ed<=y)
    {
        add[r]+=z;
        add[r]%=p;
        t[r]+=z*(ed-st+1);
        t[r]%=p;
        return ;
    }
    down(r,st,ed);
    int mid=(st+ed)>>1;
    update(r<<1|1,mid+1,ed,x,y,z);
    update(r<<1,st,mid,x,y,z);
    t[r]=t[r<<1]+t[r<<1|1];
    t[r]%=p;
}
int findm(int r,int st,int ed,int x,int y)
{
    if(st>y||ed<x) return 0;
    if(st>=x&&ed<=y) return t[r];
    down(r,st,ed);
    int mid=(st+ed)>>1;
    return (findm(r<<1,st,mid,x,y)%p+findm(r<<1|1,mid+1,ed,x,y)%p)%p;
}
void dfs1(int x,int fa,int dep)
{
    f[x]=fa;
    siz[x]=1;
    d[x]=dep;
    for(int i=0;i<edg[x].size();i++)
    {
        node tp=edg[x][i];
        if(tp.go!=fa)
        {
            dfs1(tp.go,x,dep+1);
            siz[x]+=siz[tp.go];
            if(siz[tp.go]>siz[son[x]]) son[x]=tp.go;
        }
    }
}
int cnt;
void dfs2(int x,int t)
{
    top[x]=t;
    id[x]=++cnt;
    rk[cnt]=x;
    if(!son[x]) return ;
    dfs2(son[x],t);
    for(int i=0;i<edg[x].size();i++)
    {
        node tp=edg[x][i];
        if(tp.go!=son[x]&&tp.go!=f[x]) dfs2(tp.go,tp.go);
    }
}
int sum(int x,int y)
{
    int ans=0,fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(d[fx]>d[fy])
        {
            ans+=findm(1,1,n,id[fx],id[x]);
            x=f[fx];
            ans%=p;
        }
        else
        {
            ans+=findm(1,1,n,id[fy],id[y]);
            y=f[fy];
            ans%=p;
        }
        fx=top[x];
        fy=top[y];
    }
    if(id[x]<=id[y]) ans+=findm(1,1,n,id[x],id[y]);
    else ans+=findm(1,1,n,id[y],id[x]);
    return ans%p;
}
void updateson(int x,int y,int c)
{
    int fx=top[x],fy=top[y];
    while(fx!=fy)
    {
        if(d[fx]>=d[fy])
        {
            update(1,1,n,id[fx],id[x],c);
            x=f[fx];
        }
        else
        {
            update(1,1,n,id[fy],id[y],c);
            y=f[fy];
        }
        fx=top[x];
        fy=top[y];
    }
    if(id[x]<=id[y]) update(1,1,n,id[x],id[y],c);
    else update(1,1,n,id[y],id[x],c);
}
int main()
{
    int m,r;
    sddd(n,m,r);
    sd(p);
    fup(i,1,n)
        sd(a[i]),a[i]%=p;
    fup(i,1,n-1)
    {
        int x,y;
        sdd(x,y);
        edg[x].push_back(node(y));
        edg[y].push_back(node(x));
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    while(m--)
    {

        int op,x,y,z;
        sd(op);
        if(op==1)
        {
            sddd(x,y,z);
            updateson(x,y,z%p);
        }
        else if(op==2)
        {
            sdd(x,y);
            pf(sum(x,y)%p);
        }
        else if(op==3)
        {
            sdd(x,z);
            update(1,1,n,id[x],id[x]+siz[x]-1,z%p);
        }
        else if(op==4)
        {
            sd(x);
            pf(findm(1,1,n,id[x],id[x]+siz[x]-1)%p);
        }
    }
    return 0;
}

/*
66928 66992
67095 71145
*/

猜你喜欢

转载自blog.csdn.net/qq_25973789/article/details/81078061
今日推荐