bzoj 1984: 月下“毛景树”

Description

毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

Input

第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

Output

对于毛毛虫的每个询问操作,输出一个答案。

Sample Input

4
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop

Sample Output

9
16

【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

检查了一个下午...结果竟然是存边的数组大小忘了翻倍了...给跪
这题是树链剖分..区间加和区间覆盖。维护点权变成了维护边权,我们可以把边权存成这条边到达的节点的点权,然后就和做点权的树链剖分一样了。最后两点在一条链的时候上面那个点的点权不需要加入ans。
【依旧是写了300多行的树链剖分】
#include<string>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct line
{
     int s,t,x;
     int next;
}a[200001];
int edge;
int head[100001];
inline void add(int s,int t,int x)
{
	 a[edge].next=head[s];
     head[s]=edge;
     a[edge].s=s;
     a[edge].t=t;
     a[edge].x=x;
}
struct tree
{
     int l,r;
     int max;
     int tag1,tag2;//1cover 2add
}tr[800001];
inline int max(int x,int y)
{
     if(x>y)
          return x;
     return y;
}
inline void up(int p)
{
     tr[p].max=max(tr[p*2].max,tr[p*2+1].max);
     //tr[p].s=tr[p*2].s+tr[p*2+1].s;
}
inline void down(int p)
{
     if(tr[p].tag1!=0)
     {
          tr[p*2].max=tr[p].tag1;
          tr[p*2+1].max=tr[p].tag1;
          tr[p*2].tag1=tr[p].tag1;
          tr[p*2+1].tag1=tr[p].tag1;
          tr[p*2].tag2=0;
          tr[p*2+1].tag2=0;
          tr[p].tag1=0;
          tr[p].tag2=0;
     }
     else if(tr[p].tag2!=0)
     {
     	  if(tr[p*2].tag1!=0&&tr[p*2].l!=tr[p*2].r)
     	       down(p*2);
     	  if(tr[p*2+1].tag1!=0&&tr[p*2+1].l!=tr[p*2+1].r)
     	       down(p*2+1);
          tr[p*2].max+=tr[p].tag2;
          tr[p*2+1].max+=tr[p].tag2;
          tr[p*2].tag2+=tr[p].tag2;
          tr[p*2+1].tag2+=tr[p].tag2;
          tr[p].tag2=0;
     }
}
inline void build(int p,int l,int r)
{
     tr[p].l=l;
     tr[p].r=r;
     tr[p].max=-21000000;
     if(l!=r)
     {
          int mid=(l+r)/2;
          build(p*2,l,mid);
          build(p*2+1,mid+1,r);
     }
}
inline void change(int p,int l,int r,int x)
{
     if(l<=tr[p].l&&tr[p].r<=r)
     {
     	  down(p);
          if(tr[p].max!=-21000000)
		       tr[p].max+=x;
		  else
		       tr[p].max=x;
          tr[p].tag2+=x;
     }
     else
     {
     	  down(p);
	      int mid=(tr[p].l+tr[p].r)/2;
		  if(l<=mid)
		       change(p*2,l,r,x);
		  if(r>mid)
		       change(p*2+1,l,r,x);
		  up(p);
     }
}
inline void cover(int p,int l,int r,int x)
{
     if(l<=tr[p].l&&tr[p].r<=r)
     {
     	//  down(p);
	      tr[p].max=x;
          tr[p].tag1=x;
          tr[p].tag2=0;
     }
     else
     {
     	  down(p);
	      int mid=(tr[p].l+tr[p].r)/2;
		  if(l<=mid)
		       cover(p*2,l,r,x);
		  if(r>mid)
		       cover(p*2+1,l,r,x);
		  up(p);
     }
}
inline int find(int p,int l,int r)
{
     if(l<=tr[p].l&&tr[p].r<=r)
          return tr[p].max;
     else
     {
     	  down(p);
	      int mid=(tr[p].l+tr[p].r)/2;
          int ans=-21000000;
          if(l<=mid)
               ans=max(ans,find(p*2,l,r));
          if(r>mid)
               ans=max(ans,find(p*2+1,l,r));
		  up(p);
		  return ans;
     }
}
int dep[100001],size[100001],son[100001],fa[100001];
int top[100001],w[100001];
bool fx[200001];
int lson[100001]/*最大节点位置*/,mson[100001]/*最大节点值*/;
int tot;
int s;
bool vis[100001];
inline void dfs1(int d)
{
     int i;
     for(i=head[d];i!=0;i=a[i].next)
     {
     	  int t=a[i].t;
          if(t!=fa[d]&&!vis[t])
          {
          	  // printf("%d\n",t);
          	   vis[t]=true;
          	   dep[t]=dep[d]+1;
               fa[t]=d;
               dfs1(t);
               son[d]+=son[t]+1;
               if(son[t]>=mson[d])
               {
                    mson[d]=son[t];
                    lson[d]=t;
               }
          }
     }
}
inline void dfs2(int d)
{
	 s++;
     int i;
     for(i=head[d];i!=0;i=a[i].next)
     {
          int t=a[i].t;
          if(t==lson[d])
          {
               top[t]=top[d];
               tot++;
               w[t]=tot;
               fx[i]=true;
               dfs2(t);
          }
     }
     for(i=head[d];i!=0;i=a[i].next)
     {
          int t=a[i].t;
          if(t!=fa[d]&&t!=lson[d])
          {
               top[t]=t;
               tot++;
               w[t]=tot;
               fx[i]=true;
               dfs2(t);
          }
     }
}
tree xx;
inline int ask(int s,int t)
{
	 int u=top[s],v=top[t];
	 int ans;
	 ans=-21000000;
     while(u!=v)
     {
          if(dep[u]>dep[v])
          {
          	   ans=max(ans,find(1,w[u],w[s]));
               s=fa[top[s]];
          }
          else
          {
          	   ans=max(ans,find(1,w[v],w[t]));
               t=fa[top[t]];
          }
          u=top[s];
          v=top[t];
     }
     if(w[s]<w[t])
          ans=max(ans,find(1,w[s]+1,w[t]));
     else if(w[s]>w[t])
          ans=max(ans,find(1,w[t]+1,w[s]));
     return ans;
}
inline void addx(int s,int t,int xx)
{
	 int u=top[s],v=top[t];
	 int ans;
	 ans=-21000000;
     while(u!=v)
     {
          if(dep[u]>dep[v])
          {
          	   change(1,w[u],w[s],xx);
               s=fa[top[s]];
          }
          else
          {
          	   change(1,w[v],w[t],xx);
               t=fa[top[t]];
          }
          u=top[s];
          v=top[t];
     }
     if(w[s]<w[t])
          change(1,w[s]+1,w[t],xx);
     else if(w[s]>w[t])
          change(1,w[t]+1,w[s],xx);
}
inline void cov(int s,int t,int xx)
{
	 int u=top[s],v=top[t];
	 int ans;
	 ans=-21000000;
     while(u!=v)
     {
          if(dep[u]>dep[v])
          {
          	   cover(1,w[u],w[s],xx);
               s=fa[top[s]];
          }
          else
          {
          	   cover(1,w[v],w[t],xx);
               t=fa[top[t]];
          }
          u=top[s];
          v=top[t];
     }
     if(w[s]<w[t])
          cover(1,w[s]+1,w[t],xx);
     else if(w[s]>w[t])
          cover(1,w[t]+1,w[s],xx);
}
struct save
{
     int s,t,x;
}b[100001];
int main()
{
//	 freopen("msn.in","r",stdin);
//	 freopen("msn.out","w",stdout);
     int n;
     scanf("%d",&n);
     int i,s,t,xx;
     for(i=1;i<=n-1;i++)
     {
          scanf("%d%d%d",&b[i].s,&b[i].t,&b[i].x);
          edge++;
          add(b[i].s,b[i].t,b[i].x);
          edge++;
          add(b[i].t,b[i].s,b[i].x);
     }
     dep[1]=1;
     s=0;
     vis[1]=true;
     dfs1(1);
     top[1]=1;
     tot++;
     w[1]=tot;
     s=0;
     dfs2(1);
     build(1,1,n);
     for(i=1;i<=edge;i++)
     {
     	  if(fx[i])
     	  {
     	       int t=a[i].t;
               change(1,w[t],w[t],a[i].x);
          }
     }
	 char x[101];
	// string x;
     int sumx=0;
     while(1)
     {
          //scanf("%s",&x);
         /* cin>>x;
          int flag;
          if(x[0]=='M')
               flag=1;
          else if(x[0]=='C')
          {
          	   if(x[1]=='o')
                    flag=2;
               else if(x[1]=='h')
                    flag=4;
          }
          else if(x[0]=='A')
               flag=3;
          else if(x[0]=='S')
               break;*/
          scanf("%s",&x);
          int flag;
          if(x[0]=='M')
               flag=1;
          else if(x[0]=='C')
          {
          	   if(x[1]=='o')
                    flag=2;
               else if(x[1]=='h')
                    flag=4;
          }
          else if(x[0]=='A')
               flag=3;
          else if(x[0]=='S')
               break;
          if(flag==1)
          {
               scanf("%d%d",&s,&t);
               printf("%d\n",ask(s,t));
          }
          else if(flag==2)
          {
               scanf("%d%d%d",&s,&t,&xx);
               cov(s,t,xx);
          }
          else if(flag==3)
          {
               scanf("%d%d%d",&s,&t,&xx);
               addx(s,t,xx);
          }
          else if(flag==4)
          {
               scanf("%d%d",&s,&xx);
               if(fx[s*2-1])
               {
                    t=a[s*2-1].t;
                    cover(1,w[t],w[t],xx);
               }
               else if(fx[s*2])
               {
                    t=a[s*2].t;
                    cover(1,w[t],w[t],xx);
               }
          }
     }
     return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值