考试的时候只想到处理\(O(1)\)的边没想到维护\(O(1)\)的路径。
首先如果没有可以退一步的限制显然就是相邻两点的最短路之和。退一步的限制想到点边互换。与处理出\(dist_{i,j}\)表示\(i\)号边和\(j\)号边之间的最短路,这里为了方便将其拆成有向边。这个可以用Dij加上双向链表\(O(m^2\log m)\)求出来。
然后考虑两个点之间要维护什么东西。显然需要最短路,如果最短路两端点被前后占了,那么就需要第一条边和最后一条边都不一样,因此要求出第一条边和最后一条边都不一样的最短路。分别记为\((s_1,t_1),(s_2,t_2)\)。如果这中间两个各占了一个也不行,因此还要记录开头不为\(s_1\),结尾不为\(t_2\),以及开头不为\(s_2\),结尾不为\(t_1\)的最短路。维护这四条最短路即可。
修改直接放在线段树上就好了,时间复杂度\(O(m^2\log m+4^2q\log m)\)
code:
#include<bits/stdc++.h>
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n))
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=2e3+5,M=4e5+5,K=1e5+5,mod=1e9+7,Mod=mod-1;const ll INF=1e18+7;const db eps=1e-5;mt19937 rnd(263082);
int n,m,T,L,x,y,z,X[N*2],Y[N*2],Z[N*2],A[M];ll d[N*2][N*2];
struct Edge{int to,w,id;};vector<Edge> S[N];list<int> G[N];
struct MaT{
int S[4],T[4];ll W[4];MaT(){Me(S,-1);Me(T,-1);Me(W,0x3f);}
MaT operator +(const MaT &B)const{
MaT C;ll Ans=INF;int I1=-1,I2=-1,i,j;
for(i=0;i<4;i++) for(j=0;j<4;j++) if(T[i]^B.S[j]^1&&W[i]+B.W[j]<Ans) Ans=W[i]+B.W[j],I1=S[i],I2=B.T[j];
C.S[0]=I1;C.T[0]=I2;C.W[0]=Ans;
I1=-1;I2=-1;Ans=INF;
for(i=0;i<4;i++) for(j=0;j<4;j++) if(T[i]^B.S[j]^1&&W[i]+B.W[j]<Ans&&S[i]^C.S[0]&&B.T[j]^C.T[0]) Ans=W[i]+B.W[j],I1=S[i],I2=B.T[j];
C.S[1]=I1;C.T[1]=I2;C.W[1]=Ans;
I1=-1;I2=-1;Ans=INF;
for(i=0;i<4;i++) for(j=0;j<4;j++) if(T[i]^B.S[j]^1&&W[i]+B.W[j]<Ans&&S[i]^C.S[0]&&B.T[j]^C.T[1]) Ans=W[i]+B.W[j],I1=S[i],I2=B.T[j];
C.S[2]=I1;C.T[2]=I2;C.W[2]=Ans;
I1=-1;I2=-1;Ans=INF;
for(i=0;i<4;i++) for(j=0;j<4;j++) if(T[i]^B.S[j]^1&&W[i]+B.W[j]<Ans&&S[i]^C.S[1]&&B.T[j]^C.T[0]) Ans=W[i]+B.W[j],I1=S[i],I2=B.T[j];
C.S[3]=I1;C.T[3]=I2;C.W[3]=Ans;
return C;
}
}Bas[N][N],p,Ans,Cl;
namespace Tree{
#define ls v<<1
#define rs v<<1|1
MaT f[M];void Up(int v){f[v]=f[ls]+f[rs];}
void BD(int l=1,int r=L-1,int v=1){if(l==r) {f[v]=Bas[A[l]][A[l+1]];return;}int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);Up(v);}
void Ins(int x,MaT y,int l=1,int r=L-1,int v=1){if(l==r) {f[v]=y;return;}int m=l+r>>1;x<=m?Ins(x,y,l,m,ls):Ins(x,y,m+1,r,rs);Up(v);}
#undef ls
#undef rs
}
struct Node{int to;ll w;bool operator <(const Node &B)const{return w>B.w;};};priority_queue<Node> Q;
int main(){
freopen("1.in","r",stdin);
int i,j;scanf("%d%d%d%d",&n,&m,&T,&L);for(i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),X[2*i-2]=x,Y[2*i-2]=y,Z[2*i-2]=Z[2*i-1]=z,X[2*i-1]=y,Y[2*i-1]=x;
for(i=0;i<2*m;i++) S[X[i]].PB((Edge){Y[i],Z[i],i});
Me(d,0x3f);for(i=0;i<2*m;i++){
for(j=1;j<=n;j++) G[j].clear();
for(j=0;j<2*m;j++) G[X[j]].PB(j);
Q.push((Node){i,d[i][i]=Z[i]});
while(!Q.empty()){
Node x=Q.top();Q.pop();
for(auto j=G[Y[x.to]].begin();j!=G[Y[x.to]].end();)if(*j^x.to^1){
if(d[i][x.to]+*j<d[i][*j])Q.push((Node){*j,d[i][*j]=d[i][x.to]+Z[*j]});
auto p=j;j++;G[Y[x.to]].erase(p);
}else j++;
}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++)if(i^j){p=Cl;
for(Edge x:S[i]) for(Edge y:S[j]) d[x.id][y.id^1]<p.W[0]&&(p.W[0]=d[x.id][y.id^1],p.S[0]=x.id,p.T[0]=y.id^1);
for(Edge x:S[i]) for(Edge y:S[j]) d[x.id][y.id^1]<p.W[1]&&x.id^p.S[0]&&y.id^p.T[0]^1&&(p.W[1]=d[x.id][y.id^1],p.S[1]=x.id,p.T[1]=y.id^1);
for(Edge x:S[i]) for(Edge y:S[j]) d[x.id][y.id^1]<p.W[2]&&x.id^p.S[0]&&y.id^p.T[1]^1&&(p.W[2]=d[x.id][y.id^1],p.S[2]=x.id,p.T[2]=y.id^1);
for(Edge x:S[i]) for(Edge y:S[j]) d[x.id][y.id^1]<p.W[3]&&x.id^p.S[1]&&y.id^p.T[0]^1&&(p.W[3]=d[x.id][y.id^1],p.S[3]=x.id,p.T[3]=y.id^1);
Bas[i][j]=p;
}
}
for(i=1;i<=L;i++) scanf("%d",&A[i]);Tree::BD();
while(T--){
scanf("%d%d",&x,&y);A[x]=y;
if(x^L) Tree::Ins(x,Bas[y][A[x+1]]);
if(x^1) Tree::Ins(x-1,Bas[A[x-1]][y]);
printf("%lld\n",Tree::f[1].W[0]<2e17?Tree::f[1].W[0]:-1);
}
}
标签:MaT,LOJ,ll,2842,JOISC,int,using,短路,define
From: https://www.cnblogs.com/275307894a/p/17024929.html