树链剖分 月下毛景树

未完成

#include<cstdio>
#include<iostream>
using namespace std;
struct ss
{
 int l,r,gai,jia,zhi;
} shu[400008];
int n,head[100005],next[200005],u[200005],v[200006],cnt=1,id[100005];
int deep[100005],size[100005],lc[100005][20],n1,dui[100005],lian[100005];
void jiabian(int a1,int a2,int a3)
{
 cnt++;
 next[cnt]=head[a1];
 head[a1]=cnt;
 u[cnt]=a2;
 v[cnt]=a3;
 return;
}
void shu1(int a1)
{
 printf("%d %d %d %d %d\n",shu[a1].l,shu[a1].r,shu[a1].zhi,shu[a1].gai,shu[a1].jia);
 if(shu[a1].l==shu[a1].r)
   return;
 shu1(a1*2);
 shu1(a1*2+1);
 return;
}
void gengxin(int a1)
{
 if(shu[a1].l==shu[a1].r)
   return;
 if(shu[a1].gai!=-1)
   {
    shu[a1<<1].zhi=shu[a1<<1|1].zhi=shu[a1].gai;
    shu[a1<<1].gai=shu[a1<<1|1].gai=shu[a1].gai;
    shu[a1<<1].jia=shu[a1<<1|1].jia=0;
    shu[a1].gai=-1;
   }
 if(shu[a1].jia!=0)
   {
    shu[a1*2].zhi+=shu[a1].jia;
    if(shu[a1*2].gai==-1)
      shu[a1*2].jia+=shu[a1].jia;
    else
      shu[a1*2].gai+=shu[a1].jia;
    if(shu[a1*2+1].gai==-1)
      shu[a1*2+1].jia+=shu[a1].jia;
    else
      shu[a1*2+1].gai+=shu[a1].jia;
    shu[a1<<1|1].zhi+=shu[a1].jia;
    shu[a1].jia=0;
   }
}
void xianjia(int a1,int a2,int a3,int a4)
{
 if(shu[a1].l>=a2&&shu[a1].r<=a3)
   {
    shu[a1].zhi+=a4;
    if(shu[a1].gai!=-1)
      shu[a1].gai+=a4;
    else
      shu[a1].jia+=a4;
    return;
   }
 gengxin(a1);
 int mid=(shu[a1].l+shu[a1].r)>>1;
 if(a2<=mid)
   xianjia(a1<<1,a2,a3,a4);
 if(a3>mid)
   xianjia(a1<<1|1,a2,a3,a4);
    shu[a1].zhi=max(shu[a1<<1].zhi,shu[a1<<1|1].zhi);
    return;
}
void build(int a1,int a2,int a3)
{
 shu[a1].l=a2;
 shu[a1].r=a3;
 shu[a1].gai=-1;
 if(a2==a3)
   return;
 int mid=(a2+a3)>>1;
 build(a1<<1,a2,mid);
 build(a1<<1|1,mid+1,a3);
 return;
}
void dfs1(int a1,int a2)
{
 size[a1]=1;
 for(int i=1;i<=16;i++)
   {
    if(deep[a1]<1<<i)
      break;
    lc[a1][i]=lc[lc[a1][i-1]][i-1];
   }
 for(int i=head[a1];i;i=next[i])
   if(u[i]!=a2)
     {
      deep[u[i]]=deep[a1]+1;
      lc[u[i]][0]=a1;
      dfs1(u[i],a1);
      size[a1]+=size[u[i]];
  }
 return;
}
void dfs2(int a1,int a2)
{
 n1++;
 dui[a1]=n1;
 lian[a1]=a2;
 int k=0;
 for(int i=head[a1];i;i=next[i])
   if(deep[a1]<deep[u[i]])
     {
      if(size[u[i]]>size[k])
        k=u[i];
  }
   else
     {
       xianjia(1,dui[a1],dui[a1],v[i]);
       id[i>>1]=a1;
       //shu1(1);
       //printf("\n");
     }
 if(k==0)
   return;
 dfs2(k,a2);
 for(int i=head[a1];i;i=next[i])
   if(deep[a1]<deep[u[i]]&&k!=u[i])
     dfs2(u[i],u[i]);
}
int lca(int a1,int a2)
{
 if(deep[a1]<deep[a2])
   swap(a1,a2);
 int t=deep[a1]-deep[a2];
 for(int i=0;i<=16;i++)
   if(t&(1<<i))
     a1=lc[a1][i];
 for(int i=16;i>=0;i--)
   if(lc[a1][i]!=lc[a2][i])
     {
      a1=lc[a1][i];
      a2=lc[a2][i];
  }
 if(a1==a2)
   return a1;
 else
   return lc[a1][0];
}
void lianjia(int a1,int a2,int a3)
{
 for(;lian[a1]!=lian[a2];)
   {
    xianjia(1,dui[lian[a1]],dui[a1],a3);
    a1=lc[lian[a1]][0];
   }
 if(dui[a2]+1<=dui[a1])
   xianjia(1,dui[a2]+1,dui[a1],a3);
 return;
}
void xiangai(int a1,int a2,int a3,int a4)
{
 if(shu[a1].l>=a2&&shu[a1].r<=a3)
   {
    shu[a1].zhi=a4;
    shu[a1].gai=a4;
    return;
   }
 gengxin(a1);
 int mid=(shu[a1].l+shu[a1].r)>>1;
 if(a2<=mid)
   xiangai(a1<<1,a2,a3,a4);
 if(a3>mid)
   xiangai(a1<<1|1,a2,a3,a4);
    shu[a1].zhi=max(shu[a1<<1].zhi,shu[a1<<1|1].zhi);
    return;
}
void liangai(int a1,int a2,int a3)
{
 for(;lian[a1]!=lian[a2];)
   {
    xiangai(1,dui[lian[a1]],dui[a1],a3);
    a1=lc[lian[a1]][0];
   }
 if(dui[a2]+1<=dui[a1])
   xiangai(1,dui[a2]+1,dui[a1],a3);
 return;
}
int xianmax(int a1,int a2,int a3)
{
 if(shu[a1].l>=a2&&shu[a1].r<=a3)
   return shu[a1].zhi;
 gengxin(a1);
 int mid=(shu[a1].l+shu[a1].r)>>1,ma=-2147483647;
 if(a2<=mid)
   ma=max(ma,xianmax(a1<<1,a2,a3));
 if(a3>mid)
   ma=max(ma,xianmax(a1<<1|1,a2,a3));
    return ma;
}
int lianzhao(int a1,int a2)
{
 int max1=-2147483647;
 for(;lian[a1]!=lian[a2];)
   {
    max1=max(max1,xianmax(1,dui[lian[a1]],dui[a1]));
    a1=lc[lian[a1]][0];
   }
 if(dui[a2]+1<=dui[a1])
   max1=max(max1,xianmax(1,dui[a2]+1,dui[a1]));
 return max1;
}
void xunwen()
{
 char ch[10];
 for(;1;)
 {
  int a1,a2,a3,t;
  scanf("%s",ch);
  if(ch[1]==‘t‘)
    return;
  scanf("%d%d",&a1,&a2);
  if(ch[1]==‘a‘)
    { 
      t=lca(a1,a2);
      printf("%d\n",max(lianzhao(a1,t),lianzhao(a2,t)));
    }
  if(ch[1]==‘d‘)
    {
      scanf("%d",&a3);
   t=lca(a1,a2);
   //printf("%d %d\n",t,t);
   lianjia(a1,t,a3);
   lianjia(a2,t,a3); 
    }
  if(ch[1]==‘o‘)
    {
     scanf("%d",&a3);
     t=lca(a1,a2);
    // printf("%d %d\n",t,t);
     liangai(a1,t,a3);
     liangai(a2,t,a3);
    }
  if(ch[1]==‘h‘)
  {
    xiangai(1,dui[id[a1]],dui[id[a1]],a2);
    //shu1(1);printf("\n");
     }
 }
}
int main()
{
 freopen("sj.txt","r",stdin);
 freopen("1.txt","w",stdout);
 scanf("%d",&n);
 for(int i=0;i<n-1;i++)
   {
    int a1,a2,a3;
    scanf("%d%d%d",&a1,&a2,&a3);
    jiabian(a1,a2,a3);
    jiabian(a2,a1,a3);
   }
 build(1,1,n);
 dfs1(1,0);
 dfs2(1,1);
 xunwen();
}

时间: 2024-11-10 07:48:52

树链剖分 月下毛景树的相关文章

【树链剖分】【分块】【最近公共祖先】【块状树】bzoj1984 月下“毛景树”

裸题,但是因为权在边上,所以要先把边权放到这条边的子节点上,然后进行链更新/查询的时候不能更新/查询其lca. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 100001 #define BN 320 #define INF 2147483647 int fa[N],dep[N],siz[N],son[N],Num[N],tot,top[N],a[N

BZOJ 1984: 月下“毛景树”( 树链剖分 )

水水的树链剖分... 将边上的权值转到深度较大的点上 , 然后要注意这样做之后修改或者查询 u , v 转到同一条重链上时 ( 假设 u 深度小 ) , 不能把 u 的权值算上 , 因为是 u 和它的 fa 的边的权值 , 从 u 到 v 并没有经过这条边 线段树维护 3 个域 set , add , max . ---------------------------------------------------------------------------- #include<cstdio

【BZOJ1984】月下“毛景树” 树链剖分+线段树

[BZOJ1984]月下"毛景树" Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的"毛景树"下面,发现树上长着他最爱吃的毛毛果~~~ "毛景树"上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的.但是这棵"毛景树"有着神奇的魔力,他能改变树枝上毛毛果的个数: ?

[BZOJ1984] 月下“毛景树”|树链剖分|线段树

1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1088  Solved: 348[Submit][Status][Discuss] Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没

P4315 月下“毛景树”

P4315 月下"毛景树" 题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树"下面,发现树上长着他最爱吃的毛毛果~ "毛景树"上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的.但是这棵"毛景树"有着神奇的魔力,他能改变树枝上毛毛果的个数: Change k w:将第k条

[luogu4315]月下“毛景树”

[luogu4315]月下"毛景树" luogu 联赛前复习一发树剖.不会告诉你WA了4发 #define ls x<<1,l,mid #define rs x<<1|1,mid+1,r #include<bits/stdc++.h> using namespace std; const int _=1e5+5; int re(){ int x=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){

BZOJ 2243:染色(树链剖分+区间合并线段树)

[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”.请你写一个程序依次完成这m个操作.Input第一行包含2个整数n和m,分别表示节点数和操作数:第二行包含n个正整数表示n个节点的初始颜色下面 行每行包含两个整数x和y,表示x和y之间有一条无向边.下面 行每行描述一个操作:“C

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写

【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)

Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改转换一下,因为那个dis非常不爽.显然s~t的路径有s~lca和lca~t组成.令d[x]表示x的深度,对于s~lca上面的点,修改的值相当于a*(d[s]-d[x])+b=-a*d[x]+(b-a*d[s]),lca~t上面的点的值相当于a*(d[s]+d[x]-2*d[lca])+b=a*d[x