932F Escape Through Leaf

传送门

题目大意

https://www.luogu.org/problemnew/show/CF932F

分析

我们可以从叶子向根每次插入b和ans

所以我们不难发现就是相当于插入线段

于是李超树+线段树合并即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int maxm = 2e5;
const int M = 1e5;
struct node {
    int k,b,le,ri;
};
node d[4000000];
int n,m,a[100100],b[100100],rt[100100],ans[100100],cnt,sum,Ans;
bool vis[4000000];
vector<int>v[100100];
inline int get(int b1,int k1,int b2,int k2){return (b2-b1)/(k1-k2);}
inline void add(int le,int ri,int wh,int B,int K){
    if(!vis[wh]){
      d[wh].k=K;
      d[wh].b=B;
      vis[wh]=1;
      return;
    }
    int f1=K*(le-M)+B,f2=d[wh].k*(le-M)+d[wh].b,f3=K*(ri-M)+B,f4=d[wh].k*(ri-M)+d[wh].b;
    if(f1>=f2&&f3>=f4)return;
    if(f1<=f2&&f3<=f4)d[wh].k=K,d[wh].b=B;
      else {
          int mid=(le+ri)>>1;
          int x=get(B,K,d[wh].b,d[wh].k)+M;
          if(f1<=f2){
            if(x>mid)d[wh].ri=(d[wh].ri?d[wh].ri:++cnt),
                        add(mid+1,ri,d[wh].ri,d[wh].b,d[wh].k),d[wh].k=K,d[wh].b=B;
              else d[wh].le=(d[wh].le?d[wh].le:++cnt),
                     add(le,mid,d[wh].le,B,K);
          }else {
            if(x<=mid)d[wh].le=(d[wh].le?d[wh].le:++cnt),
                       add(le,mid,d[wh].le,d[wh].b,d[wh].k),d[wh].k=K,d[wh].b=B;
              else d[wh].ri=(d[wh].ri?d[wh].ri:++cnt),
                     add(mid+1,ri,d[wh].ri,B,K);
          }
      }
}
inline void que(int le,int ri,int wh,int x){
    if(!wh)return;
    if(vis[wh])Ans=min(Ans,(x-M)*d[wh].k+d[wh].b);
    if(le==ri)return;
    int mid=(le+ri)>>1;
    if(mid>=x)que(le,mid,d[wh].le,x);
      else que(mid+1,ri,d[wh].ri,x);
}
inline int mer(int le,int ri,int x,int y){
    if(!x||!y)return x+y; 
    int mid=(le+ri)>>1;
    d[x].le=mer(le,mid,d[x].le,d[y].le);
    d[x].ri=mer(mid+1,ri,d[x].ri,d[y].ri);
    add(le,ri,x,d[y].b,d[y].k);
    return x;
}
inline void dfs(int x,int fa){
    for(int i=0;i<v[x].size();i++)
      if(v[x][i]!=fa){
          dfs(v[x][i],x);
          rt[x]=mer(0,maxm,rt[x],rt[v[x][i]]);
      }
    Ans=1000000000000000007ll;
    if(!rt[x])rt[x]=++cnt;
    que(0,maxm,rt[x],a[x]+M);
    if(v[x].size()==1&&v[x][0]==fa)Ans=0;
    ans[x]=Ans;
    add(0,maxm,rt[x],ans[x],b[x]);
}
signed main(){
    int i,j,k;
    scanf("%lld",&n);
    for(i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(i=1;i<=n;i++)scanf("%lld",&b[i]);
    for(i=1;i<n;i++){
      int x,y;
      scanf("%lld%lld",&x,&y);
      v[x].push_back(y);
      v[y].push_back(x);
    }
    for(i=1;i<4000000;i++)d[i].le=d[i].ri=d[i].k=d[i].b=0;
    dfs(1,0);
    for(i=1;i<=n;i++)printf("%lld ",ans[i]);
    return 0;
}
posted @ 2019-02-20 14:05  水题收割者  阅读(311)  评论(0编辑  收藏  举报