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;
}

浙公网安备 33010602011771号