hdu 5893 List wants to travel 2016ACM/ICPC沈阳赛区网络赛1002

Problem Description
A boy named List who is perfect in English. Now he wants to travel and he is making a plan. But the cost of living in same citie always changes. Now he wants to know how many different kinds of continuous same cost he has to pay for living between two cities. Can you help him? (He is so lazy to do this by himself.)
 

Input
There are multiple cases. The first line contains two positive numbers N and M(N (N<=40000) where N is the amount of cities and M (M<=50000)) is the amount of operations.Then N-1 lines where each line have 3 integers a b and c, representing that there is a bidirectionoal road between city a and city b, and the cost is c.(a != b and c <= 100000). Then there are M lines of operation. For example, "Change a b c" means changing all the costs of the road which are passed by him when he travels from city a to city b to c. "Query a b" means he wants you to tell him how many different kinds of continuous same cost he has to pay traveling from city a to city b.(if a == b, the cost is 0).
 

Output
He insure you that there is exactly one route between every two different cities.
 

Sample Input
  
  
9 3 1 2 2 2 3 1 1 7 2 1 4 2 3 5 2 3 6 1 5 8 2 5 9 3 Query 1 8 Change 2 6 3 Query 1 6
 

Sample Output
  
  
3 2

bzoj2243基本是原题

点权-->边权

当时因为一些事情耽搁,看到题目的时候只有半个小时不到了。

然后又听说不是原题就没弄。。

附2243题解链接

http://blog.csdn.net/lqybzx/article/details/42181191


这题很明显是树链剖分

我们从1开始dfs,把边权移动到深度大的那个点上

然后直接裸线段树维护答案

记得最后两条链合并的时候处理下细节就行了

P.S 强烈要求增加数据Qurey 1 1,对拍的时候从网上抓了好几个代码都出了-1

不知道怎么过的

#include<string>  
#include<cstdio>  
#include<cstring>  
#include<iostream>  
using namespace std;  
struct line  
{  
     int s,t,x;  
     int next;  
}a[300001];  
int edge;  
int head[100001];  
int fx[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 ll,rr;  
     int s;  
     int tag;  
}tr[800001];  
int val[100001];  
inline int max(int x,int y)  
{  
     if(x>y)  
          return x;  
     return y;  
}  
inline void up(int p)  
{  
     tr[p].s=tr[p*2].s+tr[p*2+1].s;  
     if(tr[p*2].rr==tr[p*2+1].ll)  
          tr[p].s--;  
     tr[p].ll=tr[p*2].ll;  
     tr[p].rr=tr[p*2+1].rr;  
}  
inline void down(int p)  
{  
     if(tr[p].tag!=-1)  
     {  
          tr[p*2].tag=tr[p].tag;  
          tr[p*2+1].tag=tr[p].tag;  
          tr[p*2].ll=tr[p].tag;  
          tr[p*2+1].ll=tr[p].tag;  
          tr[p*2].rr=tr[p].tag;  
          tr[p*2+1].rr=tr[p].tag;  
          tr[p*2].s=1;  
          tr[p*2+1].s=1;  
          tr[p].tag=-1;  
     }  
}  
inline void build(int p,int l,int r)  
{  
     tr[p].l=l;  
     tr[p].r=r;  
     tr[p].tag=-1;  
     if(l!=r)  
     {  
          int mid=(l+r)/2;  
          build(p*2,l,mid);  
          build(p*2+1,mid+1,r);  
          up(p);  
     }  
     else  
     {  
          tr[p].ll=val[fx[l]];  
          tr[p].rr=val[fx[l]];  
          tr[p].s=1;  
     }  
}  
inline void change(int p,int l,int r,int x)  
{  
     if(l<=tr[p].l&&tr[p].r<=r)  
     {  
          tr[p].s=1;  
          tr[p].tag=x;  
          tr[p].ll=x;  
          tr[p].rr=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);  
     }  
}  
tree xx;
inline tree find(int p,int l,int r)  
{  
	 if(l>r)
	 	return xx;
     if(l<=tr[p].l&&tr[p].r<=r)  
          return tr[p];  
     else  
     {  
          down(p);   
          int mid=(tr[p].l+tr[p].r)/2;  
          bool flag1=false,flag2=false;  
          tree x1,x2;  
          if(l<=mid)  
          {  
               x1=find(p*2,l,r);  
               flag1=true;  
          }  
          if(r>mid)  
          {  
               x2=find(p*2+1,l,r);  
               flag2=true;  
          }  
          tree x;  
          if(flag1)  
          {  
               if(flag2)  
               {  
                    x.s=x1.s+x2.s;  
                    if(x1.rr==x2.ll)  
                         x.s--;  
                    x.ll=x1.ll;  
                    x.rr=x2.rr;  
               }  
               else  
                    x=x1;  
          }  
          else  
               x=x2;  
          up(p);  
          return x;  
     }  
}  
int dep[100001],size[100001],son[100001],fa[100001];  
int top[100001],w[100001];  
int lson[100001]/*最大节点位置*/,mson[100001]/*最大节点值*/;  
int tot;  
inline void dfs1(int d)  
{  
	 mson[d]=0;
	 lson[d]=0;
	 son[d]=0;
     int i;  
     for(i=head[d];i!=0;i=a[i].next)  
     {  
          int t=a[i].t;  
          if(t!=fa[d])  
          {  
          	   val[t]=a[i].x;
               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)  
{  
     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[tot]=t;  
               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[tot]=t;  
               dfs2(t);  
          }  
     }  
}  
inline tree ask(int s,int t)  
{  
     int u=top[s],v=top[t];  
     tree x1,x2,xt;  
     x1=xx;  
     x2=xx;  
     while(u!=v)  
     {  
          if(dep[u]>dep[v])  
          {  
               xt=find(1,w[u],w[s]);  
               if(x1.s!=0)  
               {  
                    x1.s+=xt.s;  
                    if(x1.ll==xt.rr)  
                         x1.s--;  
                    x1.ll=xt.ll;  
               }  
               else  
                    x1=xt;  
               s=fa[top[s]];  
          }  
          else  
          {  
               xt=find(1,w[v],w[t]);  
               if(x2.s!=0)  
               {  
                    x2.s+=xt.s;  
                    if(x2.ll==xt.rr)  
                         x2.s--;  
                    x2.ll=xt.ll;  
               }  
               else  
                    x2=xt;  
               t=fa[top[t]];  
          }  
          u=top[s];  
          v=top[t];  
     }  
     tree x;  
     if(w[s]<w[t])  
     {  
          xt=find(1,w[s]+1,w[t]);  
          x.s=x1.s+xt.s+x2.s;  
          if(x1.ll==xt.ll)  
               x.s--;  
          if(x2.ll==xt.rr)  
               x.s--;  
          x.ll=x1.rr;  
          x.rr=x2.rr;  
     }  
     else  
     {  
          xt=find(1,w[t]+1,w[s]);  
          if(w[t]+1<=w[s])
          {
               x.s=x1.s+xt.s+x2.s;  
               if(x1.ll==xt.rr&&xt.rr!=0)  
                    x.s--;  
               if(x2.ll==xt.ll&&xt.ll!=0)  
                    x.s--;  
               x.ll=x1.rr;  
               x.rr=x2.rr;  
          }
          else
          {
               x.s=x1.s+x2.s;  
               if(x1.ll==x2.ll)  
                    x.s--;
               x.ll=x1.rr;  
               x.rr=x2.rr;  
          }
     }  
     return x;  
}  
inline void cover(int s,int t,int x)  
{  
     int u=top[s],v=top[t];  
     while(u!=v)  
     {  
          if(dep[u]>dep[v])  
          {  
               change(1,w[u],w[s],x);  
               s=fa[top[s]];  
          }  
          else  
          {  
               change(1,w[v],w[t],x);  
               t=fa[top[t]];  
          }  
          u=top[s];  
          v=top[t];  
     }  
     if(w[s]<w[t])
          change(1,w[s]+1,w[t],x);
     else if(w[s]>w[t])
          change(1,w[t]+1,w[s],x);
}  
int main()  
{  
     int n,m;  
     while(scanf("%d%d",&n,&m)!=EOF)
	 {  
	     int i,s,t,x;  
	   //  for(i=1;i<=n;i++)  
	   //       scanf("%d",&val[i]);   
	   	 edge=0;
	   	 memset(head,0,sizeof(head)); 
	     for(i=1;i<=n-1;i++)  
	     {  
	          scanf("%d%d%d",&s,&t,&x);  
	          edge++;  
	          add(s,t,x);  
	          edge++;  
	          add(t,s,x);  
	     }  
	     memset(fa,0,sizeof(fa));
	     tot=0;
	     dep[1]=1;  
	     dfs1(1);  
	     top[1]=1;  
	     tot++;  
	     w[1]=tot;  
	     fx[tot]=1;  
	     dfs2(1);  
	     build(1,1,n);  
	     string xx;  
	     int st;  
	     for(i=1;i<=m;i++)  
	     {  
	          cin>>xx;
	          if(xx=="Query")  
	          {  
	               scanf("%d%d",&s,&t);  
	               if(s!=t)
	                    printf("%d\n",ask(s,t).s);  
	               else
	                	printf("0\n");
	          }  
	          else if(xx=="Change")  
	          {  
	               scanf("%d%d%d",&s,&t,&st);  
	               if(s==t)
	                    continue;
	               cover(s,t,st);  
	          }  
	     }  
 	 }
     return 0;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值