P5025 [SNOI2017] 炸弹

Sol

线段树优化建图板子。

跑完建图以后就 tarjan 以下跑个最长路就行了。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 2500010,MOD = 1e9 + 7;
int n;
pair <LL,LL> a[N];
struct node {
	int l,r,id;
}tr[4 * N];
int id[N];
int idx;
vector <int> g[N],g2[N];
int dfn[N],low[N],timestamp;
int stk[N];
int top;
bool in_stk[N];
int scc_id[N],scc_cnt;
PII b[N];
PII c[N];
bool vis[N];
void build (int u,int l,int r) {
	tr[u] = {l,r,++idx};
	b[idx] = {l,r};
	if (l == r) {
		id[l] = idx;
		return ;
	}
	int mid = l + r >> 1;
	build (u << 1,l,mid),build (u << 1 | 1,mid + 1,r);
	g[tr[u].id].pb (tr[u << 1].id),g[tr[u].id].pb (tr[u << 1 | 1].id);
}
void modify (int u,int l,int r,int i) {
	if (l <= tr[u].l && tr[u].r <= r) {
		if (i == tr[u].id) return ;
		g[i].pb (tr[u].id);
		return ;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if (l <= mid) modify (u << 1,l,r,i);
	if (r >= mid + 1) modify (u << 1 | 1,l,r,i);
}
void tarjan (int u) {
	dfn[u] = low[u] = ++timestamp;
	stk[++top] = u;
	in_stk[u] = 1;
	for (int v : g[u]) {
		if (!dfn[v]) {
			tarjan (v);
			tomin (low[u],low[v]);
		}
		else if (in_stk[v]) tomin (low[u],dfn[v]);
	}
	if (low[u] == dfn[u]) {
		scc_cnt++;
		c[scc_cnt] = {1e9,-1e9};
		do {
			tomin (c[scc_cnt].x,b[stk[top]].x);
			tomax (c[scc_cnt].y,b[stk[top]].y);
			scc_id[stk[top]] = scc_cnt;
			in_stk[stk[top]] = 0;
		}
		while (stk[top--] != u) ;
	}
}
void DFS (int u) {
	if (vis[u]) return ;
	vis[u] = 1;
	for (int v : g2[u]) {
		DFS (v);
		tomin (c[u].x,c[v].x),tomax (c[u].y,c[v].y);
	}
}
void mian () {
	cin >> n;
	for (int i = 1;i <= n;i++) cin >> a[i].x >> a[i].y;
	sort (a + 1,a + n + 1);
	build (1,1,n);
	for (int i = 1;i <= n;i++) {
		int l = 1,r = i;
		while (l < r) {
			int mid = l + r >> 1;
			if (a[i].x - a[i].y <= a[mid].x) r = mid;
			else l = mid + 1;
		}
		int pl = l;
		l = i,r = n;
		while (l < r) {
			int mid = l + r + 1 >> 1;
			if (a[mid].x <= a[i].x + a[i].y) l = mid;
			else r = mid - 1;
		}
		b[id[i]] = {pl,l};
		modify (1,pl,l,id[i]);
	}
	tarjan (1);
	for (int i = 1;i <= idx;i++) {
		for (int j : g[i]) {
			if (scc_id[i] != scc_id[j]) g2[scc_id[i]].pb (scc_id[j]);
		}
	}
	for (int i = 1;i <= scc_cnt;i++) DFS (i);
	LL ans = 0;
	for (int i = 1;i <= n;i++) ans += (LL)i * (c[scc_id[id[i]]].y - c[scc_id[id[i]]].x + 1);
	// for (int i = 1;i <= n;i++)cout << id[i] << "   " << scc_id[id[i]] << "    " << c[scc_id[id[i]]].x << ' ' << c[scc_id[id[i]]].y << endl;
	// cout << endl;
	cout << ans % MOD << endl;
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-14 20:13  incra  阅读(8)  评论(0)    收藏  举报