preface
The total thinking time of this question is less than \ (1 \) minutes, and got a good score of \ (0pt \)!
The reason is that I tried to solve the two-dimensional partial order problem in the time of \ (O(n) \) in T3!
subject
\(\rm 4s\ 256MB.\)
\(\ tt PPL \) likes to walk around randomly when you can't solve the problem.
\ (\ rm ZBQC \) can be regarded as a directed complete graph with \ (n \) points. Each point has a weight \ (a_ \), representing the edge weight of \ (u\rightarrow v \).
However, \ (\ rm ZBQC \) is not immutable. It is sometimes renovated. Of course, it is rarely renovated. Specifically, it has a \ (m \) renovation operation next. Each operation will change the edge weight of one edge.
On this day \ (\ tt PPL \) thought of a question when walking randomly. If he walks through the shortest path between all point pairs \ ((i,j) \), what is the total distance?
Obviously \ (\ tt PPL \) won't count. It's up to you.
\(1\le n\le 10^5;1\le m\le 3000;0\le a_i\le 10^6.\)
explain
Starting from the data range, we find that \ (m \) is very small and \ (n \) is not an order of magnitude. What's the use of thinking.
There is probably a classic \ (\ tt Trick \) here. In this complete graph, there are some special edges / points (for example, there are many modified edges in this problem). Deal with the connected blocks composed of these special edges / points, and then deal with the information between blocks.
This thing seems to have been encountered once before. Otherwise, why do I think it's a classic Trick.
Back to this problem, consider processing the shortest path inside each weakly connected block. Obviously, the total size of connected blocks will not exceed \ (m \). At this time, we can enumerate the starting points, and then use the segment tree optimization \ (\ tt dijkstra \) to get the shortest path in the block. Note that the shortest path in the block does not necessarily only go in the block, but may go out of the block and re-enter the block. In this case, we must go out to the smallest \ (a \) and come back, and then we get the contribution in the block.
The contribution of the block is very simple. You only need to find an optimal point in the block.
Time complexity \ (O(n+m^2\log_2m) \).
code
Not often!//12252024832524 #include <bits/stdc++.h> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 100005; const int INF = 0x3f3f3f3f; int n,m; int a[MAXN],suf[MAXN]; LL ans; LL Read() { LL x = 0,f = 1; char c = getchar(); while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} struct edge { int v,w; bool operator < (const edge &px)const{ return v < px.v; } }; set<edge> G[MAXN]; int f[MAXN]; int findSet(int x){if(f[x]^x)f[x]=findSet(f[x]);return f[x];} vector<int> p[MAXN]; #define lc (x<<1) #define rc (x<<1|1) int MIN[MAXN<<2],ID[MAXN<<2],lz[MAXN<<2]; void calc(int x,int val){if(MIN[x]^(INF+1))MIN[x] = Min(MIN[x],val),lz[x] = Min(lz[x],val);} void up(int x) { if(MIN[lc] <= MIN[rc]) MIN[x] = MIN[lc],ID[x] = ID[lc]; else MIN[x] = MIN[rc],ID[x] = ID[rc]; } void down(int x) { if(lz[x] == INF) return; calc(lc,lz[x]); calc(rc,lz[x]); lz[x] = INF; } void Build(int x,int l,int r,int now) { lz[x] = INF; if(l == r) {if(l^now)MIN[x] = INF;else MIN[x] = 0;ID[x] = l;return;} int mid = (l+r) >> 1; Build(lc,l,mid,now); Build(rc,mid+1,r,now); up(x); } void Change(int x,int l,int r,int ql,int qr,int val) { if(ql > qr) return; if(ql <= l && r <= qr) {calc(x,val);return;} int mid = (l+r) >> 1; down(x); if(ql <= mid) Change(lc,l,mid,ql,qr,val); if(mid+1 <= qr) Change(rc,mid+1,r,ql,qr,val); up(x); } void fk(int x,int l,int r,int pos) { if(l == r){MIN[x] = INF+1;return;}//INF+1 : unchangeable int mid = (l+r) >> 1; down(x); if(pos <= mid) fk(lc,l,mid,pos); else fk(rc,mid+1,r,pos); up(x); } int dis[MAXN],to[MAXN]; int main() { // freopen("happybean.in","r",stdin); // freopen("happybean.out","w",stdout); n = Read(); m = Read(); for(int i = 1;i <= n;++ i) a[i] = Read(),f[i] = i; for(int i = 1;i <= m;++ i) { int u = Read(),v = Read(),w = Read(); int U = findSet(u),V = findSet(v); if(U > V) f[U] = V; else f[V] = U; auto it = G[u].lower_bound(edge{v,0}); if(it->v == v) G[u].erase(it); G[u].insert(edge{v,w}); } for(int i = 1;i <= n;++ i) p[findSet(i)].emplace_back(i); suf[n+1] = INF; for(int i = n;i >= 1;-- i) { suf[i] = suf[i+1]; for(auto A : p[i]) suf[i] = Min(suf[i],a[A]); } for(int i = 1,nowmin = INF;i <= n;++ i) { if(!p[i].size()) continue; for(int j = 0,N = p[i].size()-1;j <= N;++ j) to[p[i][j]] = j; for(int j = 0,N = p[i].size()-1;j <= N;++ j)//begining { Build(1,0,N,j); for(int k = 0;k <= N;++ k)//dijkstra : pop queue { int now = ID[1],lst = 0,x = p[i][now]; dis[now] = MIN[1]; for(auto A : G[p[i][now]]) { Change(1,0,N,lst,to[A.v]-1,dis[now]+a[x]); Change(1,0,N,to[A.v],to[A.v],dis[now]+A.w); lst = to[A.v]+1; } if(lst <= N) Change(1,0,N,lst,N,dis[now]+a[x]); fk(1,0,N,now); } int wdnmd = a[p[i][j]]+Min(nowmin,suf[i+1]); for(int k = 0;k <= N;++ k) dis[k] = Min(dis[k],wdnmd); int v = INF; for(int k = 0;k <= N;++ k) ans += dis[k],v = Min(v,dis[k]+a[p[i][k]]);//inside ans += v * (n-N-1ll);//outside } for(auto A : p[i]) nowmin = Min(nowmin,a[A]); } Put(ans,'\n'); return 0; }