Solultion - P4155 [SCOI2015] 国旗计划

yuruilin2026:这道题你还做不出来?

这是一道不怎么简单的简单题。

思路

首先考虑暴力。把每名战士的作用发挥到极致,暴力跳即可。复杂度 \(O(n^2)\)

但是注意一个“跳”字。既然是跳,那为什么不用 ST 表跳?

于是维护一个 ST 表表示一个战士跳 \(2^n\) 个战士能跳到的最远的战士,然后跳就行了。跳的方式参考 LCA。

于是,没了。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 200005
using namespace std;

struct Node{
	int l, r, id;
	bool operator<(Node a){return l<a.l;}
} a[N<<1];
int go[N<<1][20], ans[N];
int n, m;

inline void prework(){
	rint tot = 1;
	for(rint i = 1; i <= n<<1; ++i){
		while(tot <= n<<1 && a[tot].l <= a[i].r)
			++tot;
		go[i][0] = tot-1;
	}
	for(rint t = 1; t < 20; ++t)
		for(rint i = 1; i <= n<<1; ++i)
			go[i][t] = go[go[i][t-1]][t-1];
	return;
}

int main(){
	scanf("%d %d", &n, &m);
	for(rint i = 1; i <= n; ++i){
		scanf("%d %d", &a[i].l, &a[i].r);
		if(a[i].r < a[i].l) a[i].r += m;
    	a[i].id = i;
	}
	sort(a+1, a+n+1);
	for(rint i = 1; i <= n; ++i)
		a[i+n] = {a[i].l+m, a[i].r+m, a[i].id};
	prework();
	for(rint i = 1; i <= n; ++i){
		rint res = 0, tot = i;
		for(rint t = 19; t >= 0; --t)
			if(a[go[tot][t]].r < a[i].l+m) tot = go[tot][t], res += 1<<t;
		ans[a[i].id] = res+2;
	}
	for(rint i = 1; i <= n; ++i)
		printf("%d ", ans[i]);
	return 0;
}

posted @ 2025-04-19 09:54  Hootime  阅读(14)  评论(0)    收藏  举报