萌新求助
查看原帖
萌新求助
226113
火羽白日生楼主2020/8/25 15:56

TLE*9

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>

//#pragma GCC optimize(2)  //吸氧
//#pragma GCC optimize(3,"Ofast","inline")  //吸臭氧

typedef long long ll;
typedef unsigned long long ull;
using namespace std;

inline int read(){
    char ch=getchar();
    int x=0,w=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return x*w;
}

int n,m,r,mod,id=0,cnt=0;
int head[1000005],a[1000005],tag[4000005],t[4000005],val[1000005];
int depth[1000005],size[1000005],son[1000005],fa[1000005],top[1000005],num[1000005];

struct node{
    int v,next;
}edge[2000005];

void add(int u,int v){
    edge[++id].v=v;
    edge[id].next=head[u];
    head[u]=id;
}

int ls(int p){
    return p<<1;
}
int rs(int p){
    return p<<1|1;
}
void pushup(int p){
    t[p]=(t[ls(p)]+t[rs(p)])%mod;
}
void build(int p,int l,int r){
    if(l==r){
        t[p]=(a[l]%mod);
        return;
    }
    int mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    pushup(p);
}
void f(int p,int l,int r,int k){
    tag[p]+=k;
    t[p]=(t[p]+k*(r-l+1))%mod;
}
void pushdown(int p,int l,int r){
    if(tag[p]){
        int mid=(l+r)>>1;
        f(ls(p),l,mid,tag[p]);
        f(rs(p),mid+1,r,tag[p]);
        tag[p]=0;
    }
}
void update(int tl,int tr,int p,int l,int r,int k){
    if(tl<=l&&r<=tr){
        f(p,l,r,k);
        return;
    }
    pushdown(p,l,r);
    int mid=(l+r)>>1;
    if(tl<=mid)
        update(tl,tr,ls(p),l,mid,k);
    if(tr>mid)
        update(tl,tr,rs(p),mid+1,r,k);
    pushup(p);
}
int query(int tl,int tr,int p,int l,int r){
    int res=0;
    if(tl<=l&&r<=tr){
        res=t[p]%mod;
        return res;
    }
    pushdown(p,l,r);
    int mid=(l+r)>>1;
    if(tl<=mid)
        res=(res+query(tl,tr,ls(p),l,mid))%mod;
    if(tr>mid)
        res=(res+query(tl,tr,rs(p),mid+1,r))%mod;
    res%=mod;
    return res;
}

void dfs1(int u,int f){
    depth[u]=depth[f]+1;//标记每个点的深度
    fa[u]=f;//标记每个点的父亲
    size[u]=1;//标记每个非叶子节点的子树大小
    int max_son=-1e9;//记录重儿子的儿子数
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].v;
        if(v==f)
            continue;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>max_son){
            son[u]=v;//标记每个非叶子节点的重儿子编号
            max_son=size[v];
        }
    }
}
void dfs2(int u,int topf){
    num[u]=++cnt;//标记每个点的新编号
    a[cnt]=val[u];//把每个点的初始值赋到新编号上来
    top[u]=topf;//标记这个点所在链的顶端
    if(!son[u])//如果没有儿子则返回
        return;
    dfs2(son[u],topf);//按先处理重儿子,再处理轻儿子的顺序递归处理
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].v;
        if(v==fa[u] || v==son[u])
            continue;
        dfs2(v,v);//对于每一个轻儿子都有一条从它自己开始的链
    }
}

int qRange(int x,int y){
    int res=0;
    while(top[x]!=top[y]){//当两个点不在同一条链上
        if(depth[top[x]]<depth[top[y]])//把x点改为所在链顶端的深度更深的那个点
            swap(x,y);
        res+=query(num[top[x]],num[x],1,1,n);//res加上x点到x所在链顶端这一段区间的点权和
        res%=mod;
        x=fa[top[x]];//把x跳到x所在链顶端的那个点的上面一个点
    }
    //直到两个点处于一条链上
    if(depth[x]>depth[y])//把x点改为深度更深的那个点
        swap(x,y);
    res=(res+query(num[x],num[y],1,1,n))%mod;//再加上此时两个点的区间和
    return res;
}
int qSon(int u){
    int res=(query(num[u],num[u]+size[u]-1,1,1,n))%mod;//子树区间右端点为id[x]+siz[x]-1
    return res;
}

void upRange(int x,int y,int k){
    k%=mod;
    while(top[x]!=top[y]){
        if(depth[top[x]]<depth[top[y]])
            swap(x,y);
        update(num[top[x]],num[x],1,1,n,k);
    }
    if(depth[x]>depth[y])
        swap(x,y);
    update(num[x],num[y],1,1,n,k);
}
void upSon(int x,int k){
    k%=mod;
    update(num[x],num[x]+size[x]-1,1,1,n,k);
}

int main(int argc, const char * argv[]) {
    n=read();m=read();r=read();mod=read();
    for(int i=1;i<=n;i++)
        val[i]=read();
    for(int i=1;i<=n-1;i++){
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    depth[0]=0;
    dfs1(r,0);
    dfs2(r,r);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int op=read();
        int x,y,z;
        if(op==1){
            x=read();y=read();z=read();
            upRange(x,y,z);
        }
        if(op==2){
            x=read();y=read();
            printf("%d\n",qRange(x,y));
        }
        if(op==3){
            x=read();z=read();
            upSon(x,z);
        }
        if(op==4){
            x=read();
            printf("%d\n",qSon(x));
        }
    }
    return 0;
}

2020/8/25 15:56
加载中...