LuoGu4155/BZOJ4444
贪心+倍增
对于一个环,套路性问题,我们直接拆开加倍,拉成链即可。
首先对于一个战士$i$,如果选了他,那么下一个战士$j$一定是所有左端点小于等于i的右端点的战士中最大的一个战士,因为这样子是最优的。
对于一个战士的下一个是哪一个的话,预处理+二分查找一下就可以了。
然后我们就直接一个一个的走就可以了。
但是我们为什么不倍增的跳呢??
于是将一个一个跳变为倍增跳,,问题就解决了。。。
代码
#include <bits/stdc++.h> #define R register #define eps 1e-12 #define INF (1<<30) #define LL long long #define LINF (1ll<<60) #define MM(x, y) memset(x, y, sizeof x) #define Fo(i, x, y) for(R int i=x; i<=y; ++i) #define Ro(i, x, y) for(R int i=x; i>=y; --i) using namespace std; template<typename T> inline T Max(R T x, R T y) {return x > y ? x : y;} template<typename T> inline T Min(R T x, R T y) {return x < y ? x : y;} template<typename T> inline void in(R T &x) { static int ch; static bool flag; for(flag=false, ch=getchar(); ch<'0'||ch>'9'; ch=getchar()) flag |= ch=='-'; for(x=0; ch>='0'&&ch<='9'; ch=getchar()) x = (x<<1) + (x<<3) + ch - '0'; x = flag ? -x : x; } /*************************************Samle*************************************/ int n, m; struct node{int l, r, id;} peo[800005]; namespace First { int f[800005][31], s[800005][31], ans[800005], p; inline bool cmp(R node x, R node y) {return x.l < y.l || (x.l == y.l && x.r < y.r);} inline int find(R int x, R int l, R int r) { R int re=p+1, mid; while(l <= r) { mid = (l + r) >> 1; if(peo[mid].l <= x) l = mid + 1, re = mid; else r = mid - 1; } return re; } inline void calc() { p = n; MM(ans, 0); Fo(i, 1, n) if(peo[i].l > peo[i].r) peo[i].r += m; else peo[++p].l = peo[i].l + m, peo[p].r = peo[i].r + m, peo[p].id = i; sort(peo+1, peo+p+1, cmp); peo[p+1].r = 2e9; Fo(i, 0, 30) Fo(j, 1, p+1) f[j][i] = p+1; Fo(i, 1, p) f[i][0] = find(peo[i].r, i+1, p+1); Fo(j, 1, 30) Fo(i, 1, p) f[i][j] = f[f[i][j-1]][j-1]; Fo(i, 1, p) { if(peo[i].id && !ans[peo[i].id]) { R int now = i, to = peo[i].l + m; Ro(j, 30, 0) if(peo[f[now][j]].r < to) now = f[now][j], ans[peo[i].id] += (1<<j); } } Fo(i, 1, n) printf("%d ", ans[i]+2); puts(""); // ans+2 -> ans中没有算第一个人,也没有算最后一个人,所以要加2 } } int main() { in(n); in(m); Fo(i, 1, n) in(peo[i].l), in(peo[i].r), peo[i].id = i; First :: calc(); return 0; }