hdu5052 树链剖分:路径最大收益(烦)

  1 #include<stdio.h>
  2 #include<string.h>
  3 int cnt,now,a[50005];
  4 int next[100005],head[100005],point[100005];
  5 int num[50005],deep[50005],son[50005],father[50005];
  6 int top[50005],tree[50005],pre[50005];
  7 int addv[200005],maxv[200005],minv[200005],best[2][200005];
  8 void scanf ( int& x , char c = 0 , int flag = 0 ) {
  9     while ( ( c = getchar () ) != '-' && ( c < '0' || c > '9' ) ) ;
 10     if ( c == '-' ) flag = 1 , x = 0 ;
 11     else x = c - '0' ;
 12     while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
 13     if ( flag ) x = -x ;
 14 }
 15 int maxx(int x,int y)
 16 {
 17     return x>y?x:y;
 18 }
 19 int minx(int x,int y)
 20 {
 21     return x<y?x:y;
 22 }
 23 void add(int x,int y)
 24 {
 25     next[++now]=head[x];
 26     head[x]=now;
 27     point[now]=y;
 28 }
 29 void dfs1(int u)
 30 {
 31     num[u]=1;
 32     for (int i=head[u];i!=0;i=next[i])
 33     {
 34         int v=point[i];
 35         if (father[u]==v) continue;
 36         father[v]=u; deep[v]=deep[u]+1;
 37         dfs1(v);
 38         num[u]+=num[v];
 39         if (son[u]==-1||num[v]>num[son[u]]) son[u]=v;
 40     }
 41 }
 42 void dfs2(int u,int lead)
 43 {
 44     top[u]=lead;
 45     tree[u]=++cnt;
 46     pre[cnt]=u;
 47     if (son[u]==-1) return;
 48     dfs2(son[u],lead);
 49     for (int i=head[u];i!=0;i=next[i])
 50     {
 51         int v=point[i];
 52         if (son[u]!=v&&father[u]!=v) dfs2(v,v);
 53     }
 54 }
 55 void pushdown(int o)
 56 {
 57     if (addv[o]!=0){
 58         addv[o*2]+=addv[o]; addv[o*2+1]+=addv[o];
 59         minv[o*2]+=addv[o]; minv[o*2+1]+=addv[o];
 60         maxv[o*2]+=addv[o]; maxv[o*2+1]+=addv[o];
 61         addv[o]=0;
 62     }
 63 }
 64 void pushup(int o)
 65 {
 66     maxv[o]=maxx(maxv[o*2],maxv[o*2+1]);
 67     minv[o]=minx(minv[o*2],minv[o*2+1]);
 68     best[0][o]=maxx(best[0][o*2],best[0][o*2+1]);
 69     best[0][o]=maxx(best[0][o],maxv[o*2+1]-minv[o*2]);
 70     best[1][o]=maxx(best[1][o*2],best[1][o*2+1]);
 71     best[1][o]=maxx(best[1][o],maxv[o*2]-minv[o*2+1]);
 72 }
 73 void build(int o,int l,int r)
 74 {
 75     addv[o]=0;
 76     if (l==r){
 77         best[0][o]=best[1][o]=0;
 78         maxv[o]=minv[o]=a[pre[l]];
 79         return;
 80     }
 81     int mid=(l+r)/2;
 82     build(o*2,l,mid); build(o*2+1,mid+1,r);
 83     pushup(o);
 84 }
 85 int query_max(int o,int l,int r,int ql,int qr)
 86 {
 87     if (ql<=l&&qr>=r) return maxv[o];
 88     int mid=(l+r)/2;
 89     pushdown(o);
 90     if (ql>mid) return query_max(o*2+1,mid+1,r,ql,qr);
 91     if (qr<=mid) return query_max(o*2,l,mid,ql,qr);
 92     return maxx(query_max(o*2+1,mid+1,r,ql,qr),query_max(o*2,l,mid,ql,qr));
 93 }
 94 int query_min(int o,int l,int r,int ql,int qr)
 95 {
 96     if (ql<=l&&qr>=r) return minv[o];
 97     int mid=(l+r)/2;
 98     pushdown(o);
 99     if (ql>mid) return query_min(o*2+1,mid+1,r,ql,qr);
100     if (qr<=mid) return query_min(o*2,l,mid,ql,qr);
101     return minx(query_min(o*2+1,mid+1,r,ql,qr),query_min(o*2,l,mid,ql,qr));
102 }
103 int query_best(int o,int l,int r,int ql,int qr,int kind)
104 {
105      if (ql<=l&&qr>=r) return best[kind][o];
106     int mid=(l+r)/2,temp;
107     pushdown(o);
108     if (ql>mid) return query_best(o*2+1,mid+1,r,ql,qr,kind);
109     if (qr<=mid) return query_best(o*2,l,mid,ql,qr,kind);
110     temp=maxx(query_best(o*2+1,mid+1,r,ql,qr,kind),query_best(o*2,l,mid,ql,qr,kind));
111     if (kind==0) return maxx(temp,query_max(o*2+1,mid+1,r,mid+1,qr)-query_min(o*2,l,mid,ql,mid));
112     else return maxx(temp,query_max(o*2,l,mid,ql,mid)-query_min(o*2+1,mid+1,r,mid+1,qr));
113 }
114 void seg_update(int o,int l,int r,int ql,int qr,int v)
115 {
116     if (ql<=l&&qr>=r){
117         minv[o]+=v;
118         maxv[o]+=v;
119         addv[o]+=v;
120         return;
121     }
122     int mid=(l+r)/2;
123     pushdown(o);
124     if (ql<=mid) seg_update(o*2,l,mid,ql,qr,v);
125     if (qr>mid) seg_update(o*2+1,mid+1,r,ql,qr,v);
126     pushup(o);
127 }
128 void change_update(int x,int y,int v)
129 {
130     int temp;
131     while (top[x]!=top[y])
132     {
133         if (deep[top[x]]<deep[top[y]]) {temp=x; x=y; y=temp; }
134         seg_update(1,1,cnt,tree[top[x]],tree[x],v);
135         x=father[top[x]];
136     }
137     if (deep[x]>deep[y]) {temp=x; x=y; y=temp; }
138     seg_update(1,1,cnt,tree[x],tree[y],v);
139 }
140 void change_query(int x,int y)//核心
141 {
142     int kmax=-0x3f3f3f3f,kmin=0x3f3f3f3f,ans=0;
143     while (top[x]!=top[y])
144         if (deep[top[x]]>deep[top[y]])
145         {
146             ans=maxx(ans,query_max(1,1,cnt,tree[top[x]],tree[x])-kmin);
147             kmin=minx(kmin,query_min(1,1,cnt,tree[top[x]],tree[x]));
148             ans=maxx(ans,query_best(1,1,cnt,tree[top[x]],tree[x],1));
149             x=father[top[x]];
150         }
151         else
152         {
153             ans=maxx(ans,kmax-query_min(1,1,cnt,tree[top[y]],tree[y]));
154             kmax=maxx(kmax,query_max(1,1,cnt,tree[top[y]],tree[y]));
155             ans=maxx(ans,query_best(1,1,cnt,tree[top[y]],tree[y],0));
156             y=father[top[y]];
157         }
158     ans=maxx(ans,kmax-kmin);
159     if (deep[x]<deep[y])
160     {
161         ans=maxx(ans,query_best(1,1,cnt,tree[x],tree[y],0));
162         ans=maxx(ans,kmax-query_min(1,1,cnt,tree[x],tree[y]));
163         ans=maxx(ans,query_max(1,1,cnt,tree[x],tree[y])-kmin);
164     }
165     else
166     {
167          ans=maxx(ans,query_best(1,1,cnt,tree[y],tree[x],1));
168         ans=maxx(ans,kmax-query_min(1,1,cnt,tree[y],tree[x]));
169         ans=maxx(ans,query_max(1,1,cnt,tree[y],tree[x])-kmin);
170     }
171     printf("%d\n",ans);
172 }
173 int main()
174 {
175     int T,i,n,x,y,q,d;
176     scanf("%d",&T);
177     while (T--)
178     {
179         scanf("%d",&n);
180         for (i=1;i<=n;i++) scanf(a[i]);
181         memset(head,0,sizeof(head));
182         memset(son,-1,sizeof(son));
183         now=cnt=0;
184         father[1]=1;  deep[1]=0;
185         for (i=1;i<n;i++)
186         {
187             scanf(x); scanf(y);
188             add(x,y); add(y,x);
189         }
190         dfs1(1); dfs2(1,1);
191         build(1,1,cnt);
192         scanf("%d",&q);
193         while (q--)
194         {
195             scanf(x); scanf(y); scanf(d);
196             change_query(x,y);
197             change_update(x,y,d);
198         }
199     }
200     return 0;
201 }

http://acm.hdu.edu.cn/showproblem.php?pid=5052

转载于:https://www.cnblogs.com/xiao-xin/articles/4032204.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值