1. 程式人生 > >poj3728The merchant樹剖+線段樹

poj3728The merchant樹剖+線段樹

++ swa names include using wap eve scanf mes

如果直接在一條直線上,那麽就建線段樹

考慮每一個區間維護最小值和最大值和答案,就符合了合並的條件,一個log輕松做

那麽在樹上只要套一個樹剖就搞定了,多一個log也不是問題

註意考慮在樹上的話每一條鏈都有可能是正著被用和反著被用,所以存兩個答案

所以維護信息只需要一個merge和一個reverse

代碼如下:

  1 #include <cstdio>
  2 #include <iostream>
  3 #define mid (l+r>>1)
  4 using namespace std;
  5 struct node
  6 {
  7     int
ma,mi,ans,rev_ans; 8 node() 9 { 10 ma=0;mi=2000000000;ans=0;rev_ans=0; 11 } 12 node(int a,int b,int c,int d) 13 { 14 ma=a;mi=b;ans=c;rev_ans=d; 15 } 16 void rever() 17 { 18 swap(ans,rev_ans); 19 } 20 } tr[400001]; 21 int N,TIME,n,m,p,q; 22 int
to[100001],nex[100001],fir[100001],w[100001],pos[100001],loc[100001]; 23 int fa[100001],size[100001],dep[100001],top[100001]; 24 node merge(node a,node b) 25 { 26 return node(max(a.ma,b.ma),min(a.mi,b.mi),max(b.ma-a.mi,max(a.ans,b.ans)),max(a.ma-b.mi,max(a.rev_ans,b.rev_ans))); 27 } 28 void add(int p,int q) 29 { 30 to[++N]=q;nex[N]=fir[p];fir[p]=N;
31 to[++N]=p;nex[N]=fir[q];fir[q]=N; 32 } 33 int build(int now,int fat) 34 { 35 fa[now]=fat;size[now]=1;dep[now]=dep[fat]+1; 36 for(int i=fir[now];i;i=nex[i]) 37 if(to[i]!=fat) 38 size[now]+=build(to[i],now); 39 return size[now]; 40 } 41 void pou(int now,int tp) 42 { 43 top[now]=tp;loc[++TIME]=now; 44 pos[now]=TIME; 45 int best=0; 46 for(int i=fir[now];i;i=nex[i]) 47 if(to[i]!=fa[now]) 48 best=best?((size[best]<size[to[i]])?to[i]:best):to[i]; 49 if(best) 50 pou(best,tp); 51 for(int i=fir[now];i;i=nex[i]) 52 if(to[i]!=fa[now] && to[i]!=best) 53 pou(to[i],to[i]); 54 } 55 void work(int now,int l,int r) 56 { 57 if(l==r) 58 { 59 tr[now]=node(w[loc[l]],w[loc[l]],0,0); 60 return; 61 } 62 work(now<<1,l,mid); 63 work(now<<1|1,mid+1,r); 64 tr[now]=merge(tr[now<<1],tr[now<<1|1]); 65 } 66 node que(int now,int l,int r,int x,int y) 67 { 68 if(l==x && r==y) 69 return tr[now]; 70 node ret=node(); 71 if(x<=mid) 72 ret=que(now<<1,l,mid,x,min(y,mid)); 73 if(y>mid) 74 ret=merge(ret,que(now<<1|1,mid+1,r,max(mid+1,x),y)); 75 return ret; 76 } 77 int main() 78 { 79 scanf("%d",&n); 80 for(int i=1;i<=n;i++) 81 scanf("%d",&w[i]); 82 for(int i=1;i<n;i++) 83 scanf("%d%d",&p,&q),add(p,q); 84 build(1,0); 85 pou(1,1); 86 work(1,1,n); 87 scanf("%d",&m); 88 for(int i=1;i<=m;i++) 89 { 90 scanf("%d%d",&p,&q); 91 node P=node(),Q=node(); 92 while(top[p]!=top[q]) 93 { 94 if(dep[top[p]]<dep[top[q]]) 95 {//work on q 96 Q=merge(que(1,1,n,pos[top[q]],pos[q]),Q); 97 q=fa[top[q]]; 98 } 99 else 100 {//work on p 101 node now=que(1,1,n,pos[top[p]],pos[p]); 102 now.rever(); 103 P=merge(P,now); 104 p=fa[top[p]]; 105 } 106 } 107 if(dep[p]<dep[q]) 108 P=merge(P,que(1,1,n,pos[p],pos[q])); 109 else 110 { 111 node now=que(1,1,n,pos[q],pos[p]); 112 now.rever(); 113 P=merge(P,now); 114 } 115 P=merge(P,Q); 116 printf("%d\n",P.ans); 117 } 118 return 0; 119 }

poj3728The merchant樹剖+線段樹