BZOJ5415:[NOI2018]归程(可持久化并查集,最短路)

Description

Input

Output

Sample Input1

1
4 3
1 2 50 1
2 3 100 2
3 4 50 1
5 0 2
3 0
2 1
4 1
3 1
3 2

Sample Output1

0
50
200
50
150

Sample Input2

1
5 5
1 2 1 2
2 3 1 2
4 3 1 2
5 3 1 2
1 5 2 1
4 1 3
5 1
5 2
2 0
4 0

Sample Output2

0
2
3
1

HINT

Solution

会了可持久化并查集这题可能会被卡的正解就很好写了……

把边按高度大小从大到小加入,用可持久化并查集记下每一个时刻并查集的联通情况,

同时用持久化的$Min[i]$数组记录$i$点所在的连通块内到点$1$的最近距离。查询的时候二分到对应时刻的并查集直接查询就行了。

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<queue>
  5 #include<algorithm>
  6 #define N (200009)
  7 using namespace std;
  8 
  9 struct Edge{int to,next,len;}edge[N<<2];
 10 struct Sgt{int ls,rs,v;};
 11 struct Line
 12 {
 13     int u,v,w,h;
 14     bool operator < (const Line &a) const {return h>a.h;}
 15 }l[N<<1];
 16 struct Node
 17 {
 18     int num,dis;
 19     bool operator < (const Node &a) const {return dis>a.dis;}
 20 };
 21 int T,n,m,u,v,w,h,q,k,s,v0,p0,ans;
 22 int dis[N],head[N],num_edge;
 23 bool vis[N];
 24 priority_queue<Node>Q;
 25 
 26 struct Chairman_Tree
 27 {
 28     Sgt a[N*40];
 29     int sgt_num,b[N],Root[N<<1];
 30     
 31     int Build(int l,int r)
 32     {
 33         int now=++sgt_num;
 34         if (l==r) {a[now].v=b[l]; return now;}
 35         int mid=(l+r)>>1;
 36         a[now].ls=Build(l,mid);
 37         a[now].rs=Build(mid+1,r);
 38         return now;
 39     }
 40     int Update(int pre,int l,int r,int x,int v)
 41     {
 42         int now=++sgt_num;
 43         a[now].ls=a[pre].ls;
 44         a[now].rs=a[pre].rs;
 45         if (l==r) {a[now].v=v; return now;}
 46         int mid=(l+r)>>1;
 47         if (x<=mid) a[now].ls=Update(a[now].ls,l,mid,x,v);
 48         else a[now].rs=Update(a[now].rs,mid+1,r,x,v);
 49         return now;
 50     }
 51     int Query(int now,int l,int r,int x)
 52     {
 53         if (l==r) return a[now].v;
 54         int mid=(l+r)>>1;
 55         if (x<=mid) return Query(a[now].ls,l,mid,x);
 56         else return Query(a[now].rs,mid+1,r,x);
 57     }
 58 }Fa,Dep,Min;
 59 
 60 inline int read()
 61 {
 62     int x=0; char c=getchar();
 63     while (c<'0' || c>'9') c=getchar();
 64     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
 65     return x;
 66 }
 67 
 68 void add(int u,int v,int w)
 69 {
 70     edge[++num_edge].to=v;
 71     edge[num_edge].next=head[u];
 72     edge[num_edge].len=w;
 73     head[u]=num_edge;
 74 }
 75 
 76 int Find(int x,int t)
 77 {
 78     int fa=Fa.Query(Fa.Root[t],1,n,x);
 79     return x==fa?x:Find(fa,t);
 80 }
 81 
 82 void Dijkstra(int s)
 83 {
 84     memset(dis,0x7f,sizeof(dis));
 85     memset(vis,0,sizeof(vis));
 86     dis[s]=0;
 87     Q.push((Node){s,0});
 88     while (!Q.empty())
 89     {
 90         int x=Q.top().num; Q.pop();
 91         if (vis[x]) continue; vis[x]=1;
 92         for (int i=head[x]; i; i=edge[i].next)
 93             if (!vis[edge[i].to] && dis[x]+edge[i].len<dis[edge[i].to])
 94             {
 95                 dis[edge[i].to]=dis[x]+edge[i].len;
 96                 Q.push((Node){edge[i].to,dis[edge[i].to]});
 97             }
 98     }
 99 }
100 
101 int main()
102 {
103     T=read();
104     while (T--)
105     {
106         Fa.sgt_num=Dep.sgt_num=Min.sgt_num=0;
107         memset(head,0,sizeof(head)); num_edge=0;
108         ans=0;
109         n=read(); m=read();
110         for (int i=1; i<=m; ++i)
111         {
112             u=read(); v=read(); w=read(); h=read();
113             l[i]=(Line){u,v,w,h};
114             add(u,v,w); add(v,u,w);
115         }
116         Dijkstra(1);
117         sort(l+1,l+m+1);
118         for (int i=1; i<=n; ++i)
119             Fa.b[i]=i, Dep.b[i]=1, Min.b[i]=dis[i];
120         Fa.Root[0]=Fa.Build(1,n);;
121         Dep.Root[0]=Dep.Build(1,n);
122         Min.Root[0]=Min.Build(1,n);
123         for (int i=1; i<=m; ++i)
124         {
125             Fa.Root[i]=Fa.Root[i-1];
126             Dep.Root[i]=Dep.Root[i-1];
127             Min.Root[i]=Min.Root[i-1];
128             int fx=Find(l[i].u,i),fy=Find(l[i].v,i);
129             if (fx==fy) continue;
130             int dfx=Dep.Query(Dep.Root[i],1,n,fx);
131             int dfy=Dep.Query(Dep.Root[i],1,n,fy);
132             if (dfx>dfy) swap(fx,fy);
133             Fa.Root[i]=Fa.Update(Fa.Root[i],1,n,fx,fy);
134             int d1=Min.Query(Min.Root[i],1,n,fx);
135             int d2=Min.Query(Min.Root[i],1,n,fy);
136             Min.Root[i]=Min.Update(Min.Root[i],1,n,fy,min(d1,d2));
137             if (dfx==dfy) Dep.Root[i]=Dep.Update(Dep.Root[i],1,n,fy,dfy+1);
138         }
139         q=read(); k=read(); s=read();
140         for (int i=1; i<=q; ++i)
141         {
142             v0=read(); p0=read();
143             v0=(v0+k*ans-1)%n+1;
144             p0=(p0+k*ans)%(s+1);
145             int L=1,R=m,A=-1;
146             while (L<=R)
147             {
148                 int mid=(L+R)>>1;
149                 if (l[mid].h>p0) A=mid,L=mid+1;
150                 else R=mid-1;
151             }
152             if (A==-1)
153             {
154                 printf("%d\n",dis[v0]);
155                 ans=dis[v0]; continue;
156             }
157             int fx=Find(v0,A);
158             ans=Min.Query(Min.Root[A],1,n,fx);
159             printf("%d\n",ans);
160         }
161     }
162 }

转载于:https://www.cnblogs.com/refun/p/10232403.html

使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值