• 树剖


    #include<bits/stdc++.h>
    
    using namespace std ;
    
    const int MAXN = 100010;
    int a[MAXN],dt[MAXN],n,m,r,p,cnt;
    int dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN],topc[MAXN],ID[MAXN],res;
    
    struct Edge{
        int to,nxt;
    }edge[MAXN];//tree's Edge -> MAXN-1
    int head[MAXN],ectr;
    void addedge(int from,int to){
        ectr++;
        edge[ectr].to = to;
        edge[ectr].nxt = head[from];
        head[from] = ectr;
    }
    
    struct Tree{
        int l ,r ,dat ,lazy ;
    }tree[MAXN<<2];
    
    void build(int q,int l,int r){
        tree[q].l=l,tree[q].r=r;
        if(l == r){
            tree[q].dat = dt[l];
            if(tree[q].dat > p) tree[q].dat%=p;
            return ;
        }
        int mid = (l+r)/2;
        build(q<<1,l,mid);
        build(q<<1|1,mid+1,r);
        tree[q].dat = tree[q<<1].dat + tree[q<<1|1].dat;
        return ;
    }
        
    void change (int q, int l, int r, int d)//?????? 
    {
        if(tree[q].l==l && tree[q].r==r)
        {
            tree[q].dat+=d*(r-l+1);
            tree[q].lazy+=d;
            return ;
        }
        int mid = ( tree[q].l + tree[q].r ) /2;//??????
        if(tree[q].lazy!=0)
        {
            change ( q<<1, tree[q].l, mid, tree[q].lazy);
            change ( q<<1|1, mid+1, tree[q].r, tree[q].lazy);
            tree[q].lazy=0;
        }
        if(r<=mid) change ( q*2, l, r, d);
        else if(l>mid) change( q*2+1, l, r, d);
        else
        {
            change ( q*2, l, mid, d) ;
            change ( q*2+1, mid+1, r, d) ;
        }
        tree[q].dat = tree[q*2].dat + tree[q*2+1].dat;
        return; 
    }
        
    int query(int q, int l, int r)
    {
        int mid = ( tree[q].l + tree[q].r ) / 2;
        if(tree[q].l==l && tree[q].r==r) return tree[q].dat;
        if(tree[q].lazy!=0)
        {
            change ( q<<1, tree[q].l, mid, tree[q].lazy);
            change ( q<<1|1, mid+1, tree[q].r, tree[q].lazy);
            tree[q].lazy=0;
        }
        if(r<=mid) return query(q<<1, l, r);
        else if(l>mid) return query(q<<1|1, l, r);
        else return ( query(q<<1, l, mid) + query(q<<1|1, mid+1, r) );
    }
    
    void BRONYA_IS_THE_BEST(int x,int y,int deep){//x -> now , y -> father
        siz[x] = 1;
        dep[x] = deep;
        fa[x] = y;
        int maxson = -1;
        for(register int i = head[x];i;i = edge[i].nxt){
            int v = edge[i].to;
            if (v==y) continue;
            BRONYA_IS_THE_BEST(v,x,deep+1);
            siz[x] += siz[v];
            if(siz[v] > maxson) {
                son[x] = v;
                maxson = siz[v];
             }
        }
        return ;
    }
    
    void TERISHA_IS_THE_CUTEST(int x ,int ct){//ct == chain_top
        ID[x] = ++cnt ;
        dt[cnt] = a[x];
        topc[x] = ct;
        if(!son[x]) return ;
        TERISHA_IS_THE_CUTEST(son[x],ct);
        for(register int i = head[x];i ;i = edge[i].nxt){
            int v = edge[i].to;
            if(v == fa[x] || v == son[x]) continue ;
            TERISHA_IS_THE_CUTEST(v,v);
        }
        return ;
    }
    
    int I_WANT_YAYI_S_XX(int x,int y){//?????????? 
        int ans = 0;
        while (topc[x] != topc[y]){//??topc???????????????ID[] 
            if(dep[x] < dep[y]) swap(x,y);//?????????? 
            res = query(1,ID[topc[x]],ID[x]);
            ans += res;
            ans %= p;
            x = fa[topc[x]];//???? 
        }
        if(dep[x] > dep[y]) swap(x,y);
        res = query(1,ID[x],ID[y]);
        ans+=res;
        ans%=p;
        return ans ;//? 
    }
    
    int CSY_IS_PSYCHO(int x){
        res = query(1,ID[x],ID[x]+siz[x]-1);
        return res ;
    }
    
    int main(){
        scanf("%d%d%d%d",&n,&m,&r,&p);//r -> root ,p -> mod
        for(register int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(register int i=1,x,y;i<n;i++){
            scanf("%d%d",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        BRONYA_IS_THE_BEST(r,0,1);//fa[r] = 0
        TERISHA_IS_THE_CUTEST(r,r);
        for(register int i=1,flag;i<=m;i++){
            scanf("%d",&flag);
            if(flag == 1){
                int tra1,tra2,tra3;
                scanf("%d%d%d",&tra1,&tra2,&tra3);
                change(1,ID[tra1],ID[tra2],tra3);
            }
            if(flag == 2){
                int tra1,tra2;
                scanf("%d%d",&tra1,&tra2);
                printf("%d",I_WANT_YAYI_S_XX(tra1,tra2));
            }
            if(flag == 3){
                int tra1,tra2;
                scanf("%d%d",&tra1,&tra2);
                change(1,ID[tra1],ID[tra1]+siz[tra1]-1,tra2);
            }
            if(flag == 4){
                int tra1;
                scanf("%d",&tra1);
                printf("%d",CSY_IS_PSYCHO(tra1));
            }
        }
    //    for(int i=1;i<=n;i++){
    //        cout<<"NODE "<<i<<": siz="<<siz[i]<<",father="<<fa[i]<<",deep="<<dep[i]<<",bigson="<<son[i]<<endl;
    //    }
    //    for(int i=1;i<=n;i++){
    //        cout<<"NODE"<<i<<": newID="<<ID[i]<<",data="<<dt[ID[i]]<<endl;//NOTICE : dt[ID[i]]
    //    }
        return 0;
    }
  • 相关阅读:
    [好文翻译]保卫你的日历
    如何使用PowerShell修改Host文件
    如何使用PowerShell修改注册表
    MSDN文章纠错Automating Microsoft SharePoint 2010 with Windows PowerShell 2.0 (book excerpt)
    如何在PowerShell中得到一个对象的所有属性名和方法名呢?
    Service Object Model
    记录一个问题的解决方法
    STSADM Sync 命令里的 – Ignoreisactive 标志位
    Javascript实现图片位置控制(鼠标拖拽 + 键盘方向键移动)源码分享
    从零开始学习jQuery (六) AJAX快餐【转】
  • 原文地址:https://www.cnblogs.com/SINXIII/p/10974500.html
Copyright © 2020-2023  润新知