ybtoj 树上取模

  • 看到这种需要对树上以及子树区间内部的树进行操作的题目,想都不用想就是树链剖分了
  • 打模板已经熟悉到爆炸了,关键是怎么样在已知条件下引入新的操作
  • 观察到新操作只有一个:取mod,怎么解决呢?
  • 这一题我们得出了两个经验
  1. 在空间允许的范围以内,一颗线段树上面可以搭载多条信息
  2. 对于节点的操作我们要注意转化成id[x]
  3. 化简的关键在与去除冗余计算
  • 思考取mod什么时候是冗余的
  1. 如果说一个数小于mod,那么他就不用被取mod
  2. 线段树可以储存的信息是区间可以进行合并的(比如众数就不行)
  • 根据上述两个事实,我们可以得出结论:存储区间最大值(因为很可能发生多次取mod来卡常数)
  • 由此就对应出来的就是pushup的写法就好
  • 最后注意输入输出:想一想一个n-1和m你找了有多久
  • 代码如下:
  • #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    #include <cctype>
    #define lson k << 1
    #define rson k << 1 | 1
    
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    
    int head[maxn],nex[maxn<<1],ver[maxn<<1],tot;
    int dep[maxn],sz[maxn],son[maxn],fa[maxn],rev[maxn],id[maxn],top[maxn],idx;
    int maxx[maxn<<2];
    int a[maxn];
    ll s[maxn<<2];
    int n,m;
    
    inline int read()
    {
        int x=0;
        char ch=getchar();
        while(ch<48||ch>57) ch=getchar();
        while(ch>=48&&ch<=57) x=x*10+ch-48,ch=getchar();
        return x;
    }
    inline void add(int x,int y)
    {
        ver[++tot]=y;
        nex[tot]=head[x];
        head[x]=tot;
    }
    inline void dfs(int x,int f)
    {
        dep[x]=dep[f]+1;fa[x]=f;sz[x]=1;
        for(int i=head[x];i;i=nex[i])
        {
            int y=ver[i];
            if(y==f) continue ;
            dfs(y,x);
            sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }
    }
    inline void dfs2(int x,int t)
    {
        id[x]=++idx;top[x]=t;rev[id[x]]=a[x];
        if(!son[x]) return ;
        dfs2(son[x],t);
        for(int i=head[x];i;i=nex[i])
        {
            int y=ver[i];
            if(y!=fa[x]&&y!=son[x])
            dfs2(y,y);
        }
    }
    inline void pushup(int k)
    {
        //printf("##%d %d %d \n",k,lson,rson);
        s[k]=s[lson]+s[rson];
        maxx[k]=maxx[lson]>maxx[rson]?maxx[lson]:maxx[rson];
    }
    inline void build(int k,int l,int r)
    {
        if(l==r)
        {
            s[k]=maxx[k]=rev[l];
            return;
        }
        int mid=l+r>>1;
        build(lson,l,mid);
        build(rson,mid+1,r);
        pushup(k);
    }
    inline void change(int k,int l,int r,int x,int v)
    {
        if(l==r)
        {
            s[k]=maxx[k]=v;
            return;
        }
        int mid=l+r>>1;//
        if(x<=mid) change(lson,l,mid,x,v);
        else change(rson,mid+1,r,x,v);
        pushup(k);
    }
    inline void change_mod(int k,int l,int r,int x,int y,int q)
    {
        if(maxx[k]<q) return; 
        if(l==r)//
        {
            s[k]%=q;
            maxx[k]=s[k];
            return;
        }
        int mid=l+r>>1;
        if(x<=mid) change_mod(lson,l,mid,x,y,q);
        if(mid<y) change_mod(rson,mid+1,r,x,y,q);// 
        pushup(k);
    }
    inline ll query(int k,int l,int r,int x,int y)
    {
        if(l>y||r<x||l>r) return 0;//
        if(l>=x&&r<=y) return s[k];
        int mid=l+r>>1;
        ll ans=0;//
        if(mid>=x) ans+=query(lson,l,mid,x,y);
        if(mid<y) ans+=query(rson,mid+1,r,x,y);
        return ans;
    }
    inline ll ask(int x,int y)
    {
        ll res=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            res+=query(1,1,n,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        res+=query(1,1,n,id[x],id[y]);
        return res;
    }
    int main()
    {
        freopen("flower.in","r",stdin);
        freopen("flower.out","w",stdout);
    //    scanf("%d%d",&n,&m);
        n=read();m=read();
        //printf("%d",n);
        for(int i=1;i<=n-1;i++)
        {
            int x,y;        
    //        scanf("%d%d",&x,&y);
            x=read();y=read();
            add(x,y);
            add(y,x);
        }
        for(int i=1;i<=n;i++) a[i]=read();//scanf("%d",&a[i]);
        dfs(1,0);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1,op,a1,a2;i<=m;i++)
        {
            op=read();
            //printf("!%d\n",op);
            a1=read();
            a2=read();
            //scanf("%d%d%d",&op,&x,&y);
            if(op==1) change_mod(1,1,n,id[a1],id[a1]+sz[a1]-1,a2);
            if(op==2) change(1,1,n,id[a1],a2);
            if(op==3) printf("%lld\n",ask(a1,a2)); 
        }
        return 0;
    }

     

posted @ 2020-10-26 13:41  ILH  阅读(246)  评论(0)    收藏  举报