点分治+单调队列TLE求助
查看原帖
点分治+单调队列TLE求助
149192
__gcd楼主2020/12/30 20:09

rt,T掉了八个点,亲测跑得比 n2n^2 还慢……

理论上是 O(nlogn)O(n\log n)

#include<bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
inline int read() {
    int x = 0; bool op = 0;
	char c = getchar();
	while(!isdigit(c))op |= (c == '-'), c = getchar() ;
	while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
	return op ? -x : x;
}
const int N = 100010;
const db eps = 1e-4;
const int INF = 1e9;
int n, L, R, tot, cnt, Siz, rt;
db ans, mid; 
int to[N << 1], nxt[N << 1], head[N], siz[N], maxi[N], len[N];
db edge[N << 1], val[N], dis[N];
bool vis[N], used[N];
struct Edge {
	int u, v; db w;
	Edge(int u = 0, int v = 0, db w = 0):
		u(u), v(v), w(w){};
}e[N];
struct Node {
	int u, fa, len; db dist;
	Node(int u = 0, int fa = 0, db dist = 0, int len = 0):
		u(u), fa(fa), dist(dist), len(len){};
};
void addedge(int u, int v, db w) {
	to[++tot] = v; edge[tot] = w; nxt[tot] = head[u]; head[u] = tot;
	return ;
}
void find(int u, int fa) {
	siz[u] = 1; maxi[u] = 0;
	for(int i = head[u]; i; i = nxt[i]) {
		if(to[i] == fa || vis[to[i]])continue;
		find(to[i], u);
		maxi[u] = max(maxi[u], siz[to[i]]);
		siz[u] += siz[to[i]];
	}
	maxi[u] = max(maxi[u], Siz - siz[u]);
	if(maxi[u] < maxi[rt])rt = u;
	return ;
}
int getdis(int u, int fa, db dist, int len) {
	dis[len] = max(dis[len], dist);
	int res = 1;
	for(int i = head[u]; i; i = nxt[i]) {
		if(to[i] == fa || vis[to[i]])continue;
		res = max(res, getdis(to[i], u, dist + edge[i] - mid, len + 1) + 1);
	}
	return res;
}
void dfz(int u) {
	memset(val, -0x3f, sizeof(val)); val[0] = 0;
	vis[u] = true;
	for(int i = head[u]; i; i = nxt[i]) {
		if(vis[to[i]])continue;
		cnt = 0; 
		int mxdis = getdis(to[i], 0, edge[i] - mid, 1);
		deque<int> q;
		int p = R - len[1], l, r;
		for(int j = 1; j <= mxdis; j++) {
			l = L - j; r = R - j;
			while(p >= l && p >= 0) {
				while(q.empty() == false && val[q.back()] <= val[p])
					q.pop_back();
				q.push_back(p--);
			}
			while(q.empty() == false && q.front() > r)q.pop_front();
			if(q.empty() == false)ans = max(ans, val[q.front()] + dis[j]);
		}
		for(int j = 1; j <= mxdis; j++) {
			val[j] = max(val[j], dis[j]);
			dis[j] = -INF;
		}
	}
	for(int i = head[u]; i; i = nxt[i]) {
		if(vis[to[i]])continue;
		Siz = siz[to[i]]; rt = 0; maxi[0] = INF;
		find(to[i], 0); dfz(rt);
	}
	return ;
}
bool check() {
	memset(vis, false, sizeof(vis));
	ans = -INF;
	Siz = n; maxi[0] = INF; rt = 0; 
	find(1, 0); dfz(rt);
	return (ans >= 0);
}
int main() {
//	freopen("test.in", "r", stdin);
//	freopen("test.out", "w", stdout);
	n = read(); L = read(); R = read(); 
	for(int i = 1; i < n; i++) {
		int u = read(), v = read(), w = read();
		addedge(u, v, w); addedge(v, u, w);
	}
	for(int i = 1; i <= n; i++)dis[i] = -INF;
	db lef = -eps, rig = 1e6 + eps;
	while(lef + eps < rig) {
		mid = (lef + rig) / 2;
		if(check())lef = mid;
		else rig = mid;
	}
	printf("%.3lf", lef);
	return 0;
}
2020/12/30 20:09
加载中...