UOJ#7. 【NOI2014】购票 点分治 斜率优化 凸包 二分

原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ7.html

题解

这题是Unknown的弱化版。

如果这个问题出在序列上,那么显然可以CDQ分治 + 斜率优化 + 凸包上二分来做。

那么它出在树上?

点分治。

写挂了好多地方调了好久,自闭了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
                        For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f|=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
const int N=200005;
const LL INF=1e18;
int n,type;
vector <int> e[N];
int fa[N];
LL d[N],p[N],q[N],lim[N];
LL dp[N];
int size[N],mx[N];
int RT,Size;
int vis[N];
void get_root(int x,int pre){
    size[x]=1,mx[x]=0;
    for (auto y : e[x])
        if (y!=pre&&!vis[y]){
            get_root(y,x);
            size[x]+=size[y];
            mx[x]=max(mx[x],size[y]);
        }
    mx[x]=max(mx[x],Size-size[x]);
    if (!RT||mx[x]<mx[RT])
        RT=x;
}
struct Point{
    LL x,y;
    Point(){}
    Point(LL _x,LL _y){
        x=_x,y=_y;
    }
}a[N];
int top;
vector <int> id;
LL Ask(LL p,LL lim){
    if (!top)
        return INF;
    int L=1,R=top-1,mid;
    LL ans=a[top].y-a[top].x*p;
    while (L<=R){
        mid=(L+R)>>1;
        if (p*(a[mid].x-a[mid+1].x)>=a[mid].y-a[mid+1].y)
            R=mid-1,ans=min(ans,a[mid].y-a[mid].x*p);
        else
            L=mid+1;
    }
    return ans;
}
bool cross(Point a,Point b,Point c){
    return (__int128)(b.x-a.x)*(c.y-a.y)-(__int128)(c.x-a.x)*(b.y-a.y)<0;
}
void Ins(Point p){
    while (top>1&&!cross(a[top-1],a[top],p))
        top--;
    a[++top]=p;
}
void upd_dp(int x){
    dp[x]=min(dp[x],Ask(p[x],lim[x])+q[x]+p[x]*d[x]);
}
vector <int> s;
void Get(int x,int pre){
    s.pb(x);
    for (auto y : e[x])
        if (y!=pre&&!vis[y])
            Get(y,x);
}
bool cmp(int a,int b){
    return lim[a]>lim[b];
}
void solve(int x){
    RT=0,get_root(x,0),x=RT;
    vector <int> id;
    id.clear();
    for (int i=x;!vis[i];i=fa[i])
        id.pb(i);
    vis[x]=1;
    int sp=Size-size[x];
    if (!vis[fa[x]]){
        Size=size[fa[x]]>size[x]?sp:size[fa[x]];
        solve(fa[x]);
    }
    for (auto y : id)
        if (y!=x&&d[y]>=lim[x])
            dp[x]=min(dp[x],dp[y]+p[x]*(d[x]-d[y])+q[x]);
    s.clear();
    for (auto y : e[x])
        if (!vis[y]&&y!=fa[x])
            Get(y,x);
    sort(s.begin(),s.end(),cmp);
    int i=0;
    top=0;
    for (auto x : id){
        while (i<s.size()&&lim[s[i]]>d[x])
            upd_dp(s[i++]);
        Ins(Point(d[x],dp[x]));
    }
    while (i<s.size())
        upd_dp(s[i++]);
    for (auto y : e[x])
        if (!vis[y]&&y!=fa[x]){
            Size=size[y]>size[x]?sp:size[y];
            solve(y);
        }
}
int main(){
    n=read(),type=read();
    For(i,2,n){
        fa[i]=read();
        d[i]=read()+d[fa[i]];
        p[i]=read();
        q[i]=read();
        lim[i]=d[i]-read();
        e[i].pb(fa[i]),e[fa[i]].pb(i);
        dp[i]=INF;
    }
    vis[0]=1,Size=n;
    solve(1);
    For(i,2,n)
        printf("%lld\n",dp[i]);
    return 0;
}

  

posted @   zzd233  阅读(258)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!

点击右上角即可分享
微信分享提示