Hdu--5052(树链剖分,线段树,*)

2014-10-10 20:24:54

思路:树链剖分是比较好想到的,关键线段树如何实现。线段树每个节点维护五个值:add,tmax(区间最大值),tmin(区间最小值),ans1(向右走最大利润),ans2(向左走最大利润)。然后ans1是由右儿子最大值 - 左儿子最小值得到,ans2反过来。然后在树剖过程中要注意方向性带来的影响。 读入优化了下。

  1 /*************************************************************************
  2     > File Name: 5052.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Fri 10 Oct 2014 07:12:29 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <queue>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 #define lp (p << 1)
 20 #define rp (p << 1|1)
 21 #define getmid(l,r) (l + (r - l) / 2)
 22 #define MP(a,b) make_pair(a,b)
 23 typedef long long ll;
 24 const int INF = 1 << 30;
 25 const int maxn = 50010;
 26 
 27 inline int Read(){
 28     int x = 0,f = 1;char c = getchar();
 29     while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
 30     while(c >= '0' && c <= '9'){x = x * 10 + c - '0';c = getchar();}
 31     return x * f;
 32 }
 33 
 34 int T,N,Q;
 35 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt;
 36 int dep[maxn],sz[maxn],son[maxn],fa[maxn],w[maxn],aw[maxn],top[maxn],tsz;
 37 int val[maxn];
 38 
 39 struct node{
 40     int add;
 41     int tmax,tmin;
 42     int ans1,ans2;
 43 }t[maxn << 2];
 44 
 45 void Add_edge(int u,int v){
 46     next[++ecnt] = first[u];
 47     ver[ecnt] = v;
 48     first[u] = ecnt;
 49 }
 50 
 51 void Dfs(int p,int pre,int d){
 52     sz[p] = 1;
 53     son[p] = -1;
 54     dep[p] = d;
 55     fa[p] = pre;
 56     int v,tmp = 0;
 57     for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){
 58         Dfs(v,p,d + 1);
 59         if(sz[v] > tmp){
 60             tmp = sz[v];
 61             son[p] = v;
 62         }
 63         sz[p] += sz[v];
 64     }
 65 }
 66 
 67 void Dfs_pos(int p,int tp){
 68     w[p] = ++tsz;
 69     aw[tsz] = p;
 70     top[p] = tp;
 71     if(son[p] != -1) Dfs_pos(son[p],tp);
 72     for(int i = first[p]; i != -1; i = next[i]){
 73         int v = ver[i];
 74         if(v != son[p] && v != fa[p])
 75             Dfs_pos(v,v);
 76     }
 77 }
 78 
 79 void Push_up(int p){
 80     t[p].tmax = max(t[lp].tmax,t[rp].tmax);
 81     t[p].tmin = min(t[lp].tmin,t[rp].tmin);
 82 
 83     t[p].ans1 = max(t[lp].ans1,t[rp].ans1);
 84     t[p].ans1 = max(t[p].ans1,t[rp].tmax - t[lp].tmin);
 85 
 86     t[p].ans2 = max(t[lp].ans2,t[rp].ans2);
 87     t[p].ans2 = max(t[p].ans2,t[lp].tmax - t[rp].tmin);
 88 }
 89 
 90 void Push_down(int p){
 91     int c = t[p].add;
 92     if(c){
 93         t[lp].add += c;
 94         t[rp].add += c;
 95         t[lp].tmax += c;
 96         t[lp].tmin += c;
 97         t[rp].tmax += c;
 98         t[rp].tmin += c;
 99         t[p].add = 0;
100     }
101 }
102 
103 void Build_tree(int p,int l,int r){
104     t[p].add = 0;
105     if(l == r){
106         t[p].tmax = t[p].tmin = val[aw[l]];
107         t[p].ans1 = t[p].ans2 = 0;
108         return;
109     }
110     int mid = getmid(l,r);
111     Build_tree(lp,l,mid);
112     Build_tree(rp,mid + 1,r);
113     Push_up(p);
114 }
115 
116 int Query_tree(int f,int a,int b,int p,int l,int r,int & maxx,int & minn){
117     if(a <= l && r <= b){
118         maxx = t[p].tmax;
119         minn = t[p].tmin;
120         if(f == 1) return t[p].ans1;
121         else return t[p].ans2;
122     }
123     int mid = getmid(l,r);
124     Push_down(p);
125     if(b <= mid) return Query_tree(f,a,b,lp,l,mid,maxx,minn);
126     else if(a > mid) return Query_tree(f,a,b,rp,mid + 1,r,maxx,minn);
127     else{
128         int maxl,maxr,minl,minr;
129         int res = max(Query_tree(f,a,b,lp,l,mid,maxl,minl),
130                 Query_tree(f,a,b,rp,mid + 1,r,maxr,minr));
131         maxx = max(maxl,maxr);
132         minn = min(minl,minr);
133         if(f == 1) return max(res,maxr - minl);
134         else return max(res,maxl - minr);
135     }
136 }
137 
138 int Find(int a,int b){
139     int f1 = top[a],f2 = top[b],maxl,maxr,minl,minr,tmax,tmin;
140     maxl = maxr = -INF;
141     minl = minr = INF;
142     int res = -INF;
143     while(f1 != f2){
144         if(dep[f1] > dep[f2]){
145             res = max(res,Query_tree(2,w[f1],w[a],1,1,tsz,tmax,tmin));
146             res = max(res,tmax - minl);
147             maxl = max(maxl,tmax);
148             minl = min(minl,tmin);
149             a = fa[f1];
150             f1 = top[a];
151         }
152         else{
153             res = max(res,Query_tree(1,w[f2],w[b],1,1,tsz,tmax,tmin));
154             res = max(res,maxr - tmin);
155             maxr = max(maxr,tmax);
156             minr = min(minr,tmin);
157             b = fa[f2];
158             f2 = top[b];
159         }
160     }
161     if(dep[a] > dep[b])
162         res = max(res,Query_tree(2,w[b],w[a],1,1,tsz,tmax,tmin));
163     else
164         res = max(res,Query_tree(1,w[a],w[b],1,1,tsz,tmax,tmin));
165     res = max(res,tmax - minl);
166     res = max(res,maxr - tmin);
167     res = max(res,maxr - minl);
168     return res;
169 }
170 
171 void Update_tree(int a,int b,int c,int p,int l,int r){
172     if(a <= l && r <= b){
173         t[p].add += c;
174         t[p].tmax += c;
175         t[p].tmin += c;
176         return;
177     }
178     Push_down(p);
179     int mid = getmid(l,r);
180     if(a <= mid) Update_tree(a,b,c,lp,l,mid);
181     if(b > mid) Update_tree(a,b,c,rp,mid + 1,r);
182     Push_up(p);
183 }
184 
185 void Change(int a,int b,int c){
186     int f1 = top[a],f2 = top[b];
187     while(f1 != f2){
188         if(dep[f1] > dep[f2]){
189             swap(a,b);
190             swap(f1,f2);
191         }
192         Update_tree(w[f2],w[b],c,1,1,tsz);
193         b = fa[f2];
194         f2 = top[b];
195     }
196     if(dep[a] > dep[b]) swap(a,b);
197     Update_tree(w[a],w[b],c,1,1,tsz);
198 }
199 
200 int main(){
201     int a,b,c;
202     T = Read();
203     while(T--){
204         memset(first,-1,sizeof(first));
205         ecnt = tsz = 0;
206         N = Read();
207         for(int i = 1; i <= N; ++i)
208             val[i] = Read();
209         for(int i = 1; i < N; ++i){
210             a = Read(),b = Read();
211             Add_edge(a,b);
212             Add_edge(b,a);
213         }
214         Dfs(1,0,0);
215         Dfs_pos(1,1);
216         Build_tree(1,1,tsz);
217         Q = Read();
218         for(int i = 1; i <= Q; ++i){
219             a = Read(),b = Read(),c = Read();
220             int ans = Find(a,b);
221             if(ans < 0) ans = 0;
222             printf("%d\n",ans);
223             Change(a,b,c);
224         }
225     }
226     return 0;
227 }

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4017727.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 支持向量机非线性回归通用MATLAB程序解析 #### 一、概述 本文将详细介绍一个基于MATLAB的支持向量机(SVM)非线性回归的通用程序。该程序采用支持向量机方法来实现数据的非线性回归,并通过不同的核函数设置来适应不同类型的数据分布。此外,该程序还提供了数据预处理的方法,使得用户能够更加方便地应用此程序解决实际问题。 #### 二、核心功能与原理 ##### 1. 支持向量机(SVM) 支持向量机是一种监督学习模型,主要用于分类和回归分析。对于非线性回归任务,SVM通过引入核技巧(kernel trick)将原始低维空间中的非线性问题转换为高维空间中的线性问题,从而实现有效的非线性建模。 ##### 2. 核函数 核函数的选择直接影响到模型的性能。本程序内置了三种常用的核函数: - **线性核函数**:`K(x, y) = x'y` - **多项式核函数**:`K(x, y) = (x'y + 1)^d` - **径向基函数(RBF)**:`K(x, y) = exp(-γ|x - y|^2)` 其中RBF核函数被广泛应用于非线性问题中,因为它可以处理非常复杂的非线性关系。本程序默认使用的是RBF核函数,参数`D`用于控制高斯核函数的宽度。 ##### 3. 数据预处理 虽然程序本身没有直接涉及数据预处理的过程,但在实际应用中,对数据进行适当的预处理是非常重要的。常见的预处理步骤包括归一化、缺失值处理等。 ##### 4. 模型参数 - **Epsilon**: ε-insensitive loss function的ε值,控制回归带宽。 - **C**: 松弛变量的惩罚系数,控制模型复杂度与过拟合的风险之间的平衡。 #### 三、程序实现细节 ##### 1. 函数输入与输出 - **输入**: - `X`: 输入特征矩阵,维度为(n, l),其中n是特征数量,l是样本数量。 - `Y`: 目标值向量,长度为l。 - `Epsilon`: 回归带宽。 - `C`: 松弛变量的惩罚系数。 - `D`: RBF核函数的参数。 - **输出**: - `Alpha1`: 正的拉格朗日乘子向量。 - `Alpha2`: 负的拉格朗日乘子向量。 - `Alpha`: 拉格朗日乘子向量。 - `Flag`: 标记向量,表示每个样本的类型。 - `B`: 偏置项。 ##### 2. 核心代码解析 程序首先计算所有样本间的核矩阵`K`,然后构建二次规划问题并求解得到拉格朗日乘子向量。根据拉格朗日乘子的值确定支持向量,并计算偏置项`B`。 - **核矩阵计算**:采用RBF核函数,通过`exp(-(sum((xi-xj).^2)/D))`计算任意两个样本之间的相似度。 - **二次规划**:构建目标函数和约束条件,使用`quadprog`函数求解最小化问题。 - **支持向量识别**:根据拉格朗日乘子的大小判断每个样本是否为支持向量,并据此计算偏置项`B`。 #### 四、程序扩展与优化 - **多核函数支持**:可以通过增加更多的核函数选项,提高程序的灵活性。 - **自动调参**:实现参数自动选择的功能,例如通过交叉验证选择最优的`Epsilon`和`C`值。 - **并行计算**:利用MATLAB的并行计算工具箱加速计算过程,特别是当样本量很大时。 #### 五、应用场景 该程序适用于需要进行非线性回归预测的场景,如经济预测、天气预报等领域。通过调整核函数和参数,可以有效应对各种类型的非线性问题。 ### 总结 本程序提供了一个支持向量机非线性回归的完整实现框架,通过灵活的核函数设置和参数调整,能够有效地处理非线性问题。对于需要进行回归预测的应用场景,这是一个非常实用且强大的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值