$bzoj$跑的太慢了......
我们考虑用线段树来解决这个问题
考虑扫描线
当扫到左端点$i$时,我们把线段$i$加入线段树
同时,对于每个左端点$i$,我们在线段树上二分出最远的$r$满足$r$被覆盖了$k$次以上
复杂度$O(n \log n)$
然后$TLE$了,这一定不是我的锅...
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define ri register int #define rep(io, st, ed) for(ri io = st; io <= ed; io ++) #define drep(io, ed, st) for(ri io = ed; io >= st; io --) extern inline char gc() { static char RR[23456], *S = RR + 23333, *T = RR + 23333; if(S == T) fread(RR, 1, 23333, stdin), S = RR; return *S ++; } inline int read() { int p = 0; char c = gc(); while(c > ‘9‘ || c < ‘0‘) c = gc(); while(c >= ‘0‘ && c <= ‘9‘) p = p * 10 + c - ‘0‘, c = gc(); return p; } int wr[50], rw; #define pc(iw) putchar(iw) inline void write(int x, char c = ‘\n‘) { if(!x) pc(‘0‘); if(x < 0) x = -x, pc(‘-‘); while(x) wr[++ rw] = x % 10, x /= 10; while(rw) pc(wr[rw --] + ‘0‘); pc(c); } const int sid = 2005000; const int tid = 8005000; int nl, nr, ans; int n, k, tn, tot; int T[sid], mx[tid], tag[tid]; struct seg { int l, r, id; friend bool operator < (seg a, seg b) { return a.l < b.l; } } t[1005000]; #define ls (o << 1) #define rs (o << 1 | 1) inline void pushdown(int o) { if(!tag[o]) return; tag[ls] += tag[o]; mx[ls] += tag[o]; tag[rs] += tag[o]; mx[rs] += tag[o]; tag[o] = 0; } int ml, mr; inline void mdf(int o, int l, int r) { if(ml <= l && mr >= r) { tag[o] ++; mx[o] ++; return; } pushdown(o); int mid = (l + r) >> 1; if(ml > mid) mdf(rs, mid + 1, r); else if(mr <= mid) mdf(ls, l, mid); else mdf(ls, l, mid), mdf(rs, mid + 1, r); mx[o] = max(mx[ls], mx[rs]); } inline int qry(int o, int l, int r) { if(l == r) { if(mx[o] >= k) return l; return 0; } pushdown(o); int mid = (l + r) >> 1; if(mx[rs] < k && mx[ls] < k) return 0; if(mx[rs] >= k) return qry(rs, mid + 1, r); else return qry(ls, l, mid); } int b[sid], f[70000]; inline void radix_sort(int *a, int n) { rep(i, 1, n) ++ f[a[i] & 65535]; rep(i, 0, 65536) f[i] += f[i - 1]; drep(i, n, 1) b[f[a[i] & 65535] --] = a[i]; memset(f, 0, sizeof(f)); rep(i, 1, n) ++ f[b[i] >> 16]; rep(i, 0, 65536) f[i] += f[i - 1]; drep(i, n, 1) a[f[b[i] >> 16] --] = b[i]; } int main() { n = read(); k = read(); rep(i, 1, n) { t[i].id = i; t[i].l = read(); t[i].r = read(); T[++ tot] = t[i].l; T[++ tot] = t[i].r; } sort(t + 1, t + n + 1); radix_sort(T, tot); tn = unique(T + 1, T + tot + 1) - T - 1; rep(i, 1, n) t[i].r = lower_bound(T + 1, T + tn + 1, t[i].r) - T; for(ri i = 1, j = 1; i <= tn; i ++) { while(j <= n && t[j].l == T[i]) { ml = i; mr = t[j].r; mdf(1, 1, tn); j ++; } int far = qry(1, 1, tn); if(T[far] - T[i] > ans) { nl = i; nr = far; ans = T[far] - T[i]; } } write(ans); int num = 0; rep(i, 1, n) { if(t[i].l <= T[nl] && nr <= t[i].r) num ++, write(t[i].id, ‘ ‘); if(num == k) break; } return 0; }
bzoj5102 [POI2018]Prawnicy 线段树
原文:https://www.cnblogs.com/reverymoon/p/9952445.html