[joint examination of noip improvement group on November 11, 2021] happy bean problem solution

Keywords: Algorithm Graph Theory

[joint examination of noip improvement group on November 11, 2021] happy bean problem solution

Description

See for yourself

Solution

Think about the partial score of m=0 first
Find the shortest path from each point to all other points a x a_x ax​
This inspires us to consider only the modified edge as an undirected edge, and the internal shortest path of the connected block is formed
Let's consider how to get the answer after dealing with the shortest circuit in the block
We enumerate the source points, obviously for those outside any block z z z, ( x , z ) (x, z) (x,z) can be regarded as ( x , y ) ∪ ( y , z ) (x , y) \cup (y, z) (x,y) ∪ (y,z)(y is in the block)
So find the inside of the block d i s t ( x , y ) dist(x,y) dist(x,y) minimum y y y is OK
Consider the shortest circuit in the calculation block
In the first case, x x x outside the warp block z z z to y y y. Obviously optimal z z z satisfaction a z a_z az min
In the second case, we can only run the shortest path algorithm
If you use it here O ( m 3 ) O(m^3) O(m3) F l o y d Floyd Floyd algorithm implementation, can only get 40 p t s 40pts 40pts.
Note that there are few modified edges. We consider optimizing the shortest path algorithm based on this property
F l o y d Floyd Floyd is difficult to optimize. Consider running for each source point D i j k s t r a Dijkstra Dijkstra algorithm
Because there are many points that need to be maintained, we use segment tree to maintain, so we only need to support two operations
1. Maintain the global minimum value
2. For the current minimum value, relax all other nodes
This can be maintained with a m i n min min line segment tree implementation
How to relax?
In the most violent way
Suppose the source point is x x x. Enumerate the modified edges connected by each point, and the corresponding points will have y 1 , y 2 . . . . . y_1,y_2..... y1​,y2​.....
For each y i y_i yi , min for each point ( y i , y i + 1 ) (y_i,y_{i+1}) (yi, yi+1) interval is min
At first glance, the complexity is garbage, but each source runs once d i j dij dij will only have O ( m ) O(m) O(m) corresponding y y y. Therefore, the interval modification times of single point modification are O ( m ) O(m) O(m). So once d i j dij The complexity of dij is O ( m log ⁡ m ) O(m\log{m}) O(mlogm), so the shortest circuit in the processing block is ( O ( m 2 log ⁡ m ) ) (O(m^2\log{m})) (O(m2logm))
Then the total complexity is $O(n + m^2\log{m})

Code

#pragma GCC optimize("inline")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector","inline")
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#define LL long long
#define RE register
#define pii pair <int, int>
#define mp make_pair
#define fr first
#define sc second
#define IN inline
using namespace std;
IN int read() {
	int res = 0; char ch = getchar();
	for(; !isdigit(ch); ch = getchar());
	for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
	return res;
}
const int N = 1e5 + 10, M = 3010;
const LL inf = 1e9;
int fa[N], m, a[N], tag[M * 4], flag[M * 4], p[M], q[N], b[N];
LL ans, dis[M], n;
pii tr[M * 4];
int getfa(int x) {return fa[x] == x ? x : (fa[x] = getfa(fa[x]));}
vector <pii> edge[N];
vector <int> s[N];
pii minp(pii x, pii y) {return x < y ? x : y;}
pii operator + (pii x, pii y) {return mp(x.fr + y.fr, x.sc + y.sc);}
IN void build(int k, int l, int r) {
	tag[k] = inf, flag[k] = 0;
	if(l == r) {
		tr[k] = mp(inf, l);
		return ;
	}
	int mid = l + r >> 1;
	build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);
	tr[k] = minp(tr[k << 1], tr[k << 1 | 1]);
	return ;
}
IN void pushdown(int k) {
	if(tag[k] == inf) return ;
	int ls = k << 1, rs = k << 1 | 1;
	if(!flag[ls]) tr[ls] = minp(tr[ls], mp(tag[k], tr[ls].sc));
	if(!flag[rs]) tr[rs] = minp(tr[rs], mp(tag[k], tr[rs].sc));
	tag[ls] = min(tag[ls], tag[k]), tag[rs] = min(tag[rs], tag[k]);
	tag[k] = inf;
	return ;
}
IN pii query(int k, int l, int r, int locl, int locr) {
	if(l > r) return mp(inf, inf);
	if(l > locr || r < locl) return mp(inf, inf);
	if(flag[k]) return mp(-1, -1);
	if(locl <= l && r <= locr) return tr[k];
	pushdown(k);
	int mid = l + r >> 1;
	return minp(query(k << 1, l, mid, locl, locr), query(k << 1 | 1, mid + 1, r, locl, locr));
}
IN void modify(int k, int l, int r, int locl, int locr, int val) {
	if(l > r) return ;
	if(l > locr || r < locl) return ;
	if(flag[k]) return ;
	if(locl <= l && r <= locr) {
		tr[k] = minp(tr[k], mp(val, tr[k].sc));
		tag[k] = min(tag[k], val);
		return ;
	}
//	if(tag[k] < val) return ;
	pushdown(k);
	int mid = l + r >> 1;
	modify(k << 1, l, mid, locl, locr, val), modify(k << 1 | 1, mid + 1, r, locl, locr, val);
	tr[k] = minp(tr[k << 1], tr[k << 1 | 1]);
	return ;
}
IN void modifyflag(int k, int l, int r, int loc) {
	if(l > loc || r < loc) return ;
	if(l == r) { flag[k] = 1; return ;}
	int mid = l + r >> 1;
	modifyflag(k << 1, l, mid, loc), modifyflag(k << 1 | 1, mid + 1, r, loc);
	flag[k] = flag[k << 1] & flag[k << 1 | 1];
	return ;
}
IN void modifycaonima(int k, int l, int r, int loc, int val) {
	if(l > loc || r < loc) return ;
	if(l == r) {
		tag[k] = 0;
		tr[k] = mp(val, tr[k].sc);
		return ;
	}
	pushdown(k);
	int mid = l + r >> 1;
	modifycaonima(k << 1, l, mid, loc, val),
	modifycaonima(k << 1 | 1, mid + 1, r, loc, val);
	tr[k] = minp(tr[k << 1], tr[k << 1 | 1]);
	return ;
}
inline void dij(int s, int len) {
	build(1, 1, len);
//	printf("KAISHI %d\n",query(1, 1, n, 1, 1).fr);
	modify(1, 1, len, s, s, 0);
	while(true) {
		pii now = query(1, 1, len, 1, len);
		if(now.fr == -1) return ;
		dis[now.sc] = now.fr;
//		printf("HELLO %d %d %d %d\n",p[now.sc],now.fr,edge[p[now.sc]][0].fr,edge[p[now.sc]][0].sc + dis[now.sc]);
		LL d = dis[now.sc] + a[p[now.sc]];
		if(edge[p[now.sc]].size()) modify(1, 1, len, 1, q[edge[p[now.sc]][0].fr] - 1, d);
		else modify(1, 1, len, 1, len, d);
		for(int i = 0; i < edge[p[now.sc]].size(); ++i) {
			modify(1, 1, len, q[edge[p[now.sc]][i].fr], q[edge[p[now.sc]][i].fr], edge[p[now.sc]][i].sc + dis[now.sc]);
//			modify(1, 1, len, 1, 1,edge[p[now.sc]][i].sc + dis[now.sc]);
//			printf("Work %d %d %d %d %d\n",p[now.sc],q[edge[p[now.sc]][i].fr],edge[p[now.sc]][i].fr,edge[p[now.sc]][i].sc + dis[now.sc],query(1, 1, n, 1, 1).fr);
			if(i < edge[p[now.sc]].size() - 1) modify(1, 1, len, q[edge[p[now.sc]][i].fr] + 1, q[edge[p[now.sc]][i + 1].fr] - 1, d);
			else modify(1, 1, len, q[edge[p[now.sc]][i].fr] + 1, len, d);
		}
		modifycaonima(1, 1, len, now.sc, inf);
		modifyflag(1, 1, len, now.sc);
	}
}
void work(int x) {
//	printf("%d %d\n",x,s[x].size());
	if(s[x].size() == 1) {
		ans += (n - 1) * a[x];
		return ;
	}
	LL mnn = inf;
	for(RE int i = 1; i <= n; ++i) {
		if(getfa(b[i]) == x) continue;
		mnn = a[b[i]];
		break; 
	}
//	printf("%lld\n",mnn);
	LL len = s[x].size();
	sort(s[x].begin(), s[x].end());
	for(RE int i = 1; i <= len; ++i)
		p[i] = s[x][i - 1], q[p[i]] = i;
	LL anss = ans;
	for(RE int i = 1; i <= len; ++i) {
		LL mn = inf;
		dij(i, len);
//		printf("HELLO\n");
//		for(int j = 1; j <= len; ++j)
//			printf("OLD %d %d %d\n",p[i],p[j],dis[j]);
		for(RE int j = 1; j <= len; ++j)
			dis[j] = min(dis[j], a[p[i]] + mnn);
		for(RE int j = 1; j <= len; ++j) {
//			printf("%d %d %d\n",p[i],p[j],dis[j]);
			if(j != i) ans += dis[j];
			if(dis[j] + a[p[j]] < mn) mn = dis[j] + a[p[j]];
		}
//		printf("%lld\n",mn);
		ans += (n - len) * mn;
	}
//		printf("%lld\n",ans - anss);
}
bool cmp (int x, int y) {return a[x] < a[y];}
bool cmp1(pii x, pii y) {return x.fr < y.fr;}
signed main() {
	freopen("sample_happybean4.in","r",stdin);
//	freopen("happybean.in","r",stdin);
//	freopen("happybean.out","w",stdout);
	n = read(), m = read();
	for(RE int i = 1; i <= n; ++i)
		a[i] = read(), fa[i] = b[i] = i;
	sort(b + 1, b + n + 1, cmp);
	for(RE int i = 1; i <= m; ++i) {
		int x = read(), y = read(), z = read();
		edge[x].push_back(mp(y, z));
		fa[getfa(y)] = getfa(x);
	} 
//	for(int i = 1; i <= n; ++i)
//		printf("%d %d\n",i,getfa(i));
	for(RE int i = 1; i <= n; ++i) 
		s[getfa(i)].push_back(i), sort(edge[i].begin(), edge[i].end());
	for(RE int i = 1; i <= n; ++i) 
		if(getfa(i) == i) work(i);
	printf("%lld\n",ans);
	return 0;
}

Longer than my polynomial board Q W Q QWQ QWQ

Posted by gobbles on Fri, 12 Nov 2021 12:58:20 -0800