首页 > 代码库 > 【SPOJ Query on a tree 】 (树链剖分)

【SPOJ Query on a tree 】 (树链剖分)

http://acm.hust.edu.cn/vjudge/problem/13013

题意:

有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个权值,要求模拟两种操作:

1:QUERY x y 求节点x和节点y之间的路径中权值最大的边。

2:CHANGE p k修改第p条边的权值为k。

 

【分析】

  树链剖分裸题。。

  【表示我一开始怎么TLE,后来怎么AC的并不知道。。

 

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 using namespace std;
  8 #define Maxn 10010
  9 #define INF 0x7fffffff
 10 
 11 int mymax(int x,int y) {return x>y?x:y;}
 12 
 13 struct node
 14 {
 15     int x,y,c,next;
 16 }t[2*Maxn];int len;
 17 
 18 int first[Maxn];
 19 void ins(int x,int y,int c)
 20 {
 21     t[++len].x=x;t[len].y=y;t[len].c=c;
 22     t[len].next=first[x];first[x]=len;
 23 }
 24 
 25 char s[110];
 26 
 27 int son[Maxn],dfn[Maxn],top[Maxn],cnt;
 28 int sm[Maxn],fa[Maxn],id[Maxn],dep[Maxn];
 29 void dfs1(int x,int f)
 30 {
 31     dep[x]=dep[f]+1;
 32     sm[x]=1;son[x]=0;fa[x]=f;
 33     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
 34     {
 35         int y=t[i].y;
 36         dfs1(y,x);
 37         sm[x]+=sm[y];
 38         if(son[x]==0||sm[son[x]]<sm[y]) son[x]=y;
 39     }
 40 }
 41 
 42 void dfs2(int x,int tp)
 43 {
 44     dfn[x]=++cnt;top[x]=tp;
 45     if(son[x]) dfs2(son[x],tp);
 46     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
 47      dfs2(t[i].y,t[i].y);
 48 }
 49 
 50 struct nnode
 51 {
 52     int l,r,lc,rc,mx;
 53 }tr[2*Maxn];int tot;
 54 
 55 int build(int l,int r)
 56 {
 57     int x=++tot;
 58     tr[x].l=l;tr[x].r=r;
 59     int mid=(l+r)>>1;
 60     if(l!=r)
 61     {
 62         tr[x].lc=build(l,mid);
 63         tr[x].rc=build(mid+1,r);
 64     }
 65     tr[x].mx=-INF;
 66     return x;
 67 }
 68 
 69 void change(int x,int y,int z)
 70 {
 71     if(tr[x].l==tr[x].r)
 72     {
 73         tr[x].mx=z;
 74         return;
 75     }
 76     int mid=(tr[x].l+tr[x].r)>>1;
 77     if(y<=mid) change(tr[x].lc,y,z);
 78     else change(tr[x].rc,y,z);
 79     tr[x].mx=mymax(tr[tr[x].lc].mx,tr[tr[x].rc].mx);
 80 }
 81 
 82 int query(int x,int l,int r)
 83 {
 84     if(tr[x].l==l&&tr[x].r==r) return tr[x].mx;
 85     int mid=(tr[x].l+tr[x].r)>>1;
 86     if(r<=mid) return query(tr[x].lc,l,r);
 87     else if(l>mid) return query(tr[x].rc,l,r);
 88     return mymax(query(tr[x].lc,l,mid),query(tr[x].rc,mid+1,r));
 89 }
 90 
 91 int get_ans(int x,int y)
 92 {
 93     int mx=0;
 94     while(top[x]!=top[y])
 95     {
 96         if(dep[top[x]]<dep[top[y]]) swap(x,y);
 97         mx=mymax(mx,query(1,dfn[top[x]],dfn[x]));
 98         x=fa[top[x]];
 99     }
100     if(x==y) return mx;
101     if(dep[x]>dep[y]) swap(x,y);
102     mx=mymax(mx,query(1,dfn[x]+1,dfn[y]));
103     return mx;
104 }
105 
106 int main()
107 {
108     int T;
109     scanf("%d",&T);
110     while(T--)
111     {
112         int n;
113         scanf("%d",&n);
114         len=0;
115         memset(first,0,sizeof(first));
116         for(int i=1;i<n;i++)
117         {
118             int x,y,c;
119             scanf("%d%d%d",&x,&y,&c);
120             ins(x,y,c);ins(y,x,c);
121         }
122         dep[0]=0;dfs1(1,0);
123         cnt=0;dfs2(1,1);
124         tot=0;build(1,n);
125         for(int i=1;i<=len;i+=2)
126         {
127             if(fa[t[i].x]==t[i].y) id[(i+1)/2]=t[i].x;
128             else id[(i+1)/2]=t[i].y;
129             change(1,dfn[id[(i+1)/2]],t[i].c);
130         }
131         while(1)
132         {
133             scanf("%s",s);
134             if(s[0]==D) break;
135             int x,y;
136             scanf("%d%d",&x,&y);
137             if(s[0]==C)
138             {
139                 change(1,dfn[id[x]],y);
140             }
141             else
142             {
143                 printf("%d\n",get_ans(x,y));
144             }
145         }
146     }
147     return 0;
148 }
View Code

 

2017-01-21 11:45:00

 

【SPOJ Query on a tree 】 (树链剖分)