arc068 E: Snuke Line
首先要知道 (m/1 + m/2 + ... + m/m) 约为 mlogm
还有一个比较明显的结论,如果一个纪念品区间长度大于d,那么如果列车的停车间隔小于等于d,则这个纪念品一定能被买到
然后把区间按长度排序
枚举d,边枚举边加那些长度小于d的区间到线段树当中,这样可以保证一个纪念品不会被加2次
最后输出答案即可
#include <iostream> #include <algorithm> using namespace std; const int Maxn = 4*111111; namespace seqtree { struct Tree { Tree *ch[2]; long long _v, label; int Num, _l, _r, mid; Tree() { _v = label = 0; Num = 1; } void update(); void maintain(); }Node[Maxn], *null, *Root; int tot = 0, _k, _L, _R; long long v; void Tree::update() { if(!label) return; _v += Num*label; if(Num != 1) ch[0]->label += label, ch[1]->label += label; label = 0; } void Tree::maintain() { ch[0]->update(); ch[1]->update(); _v = ch[0]->_v + ch[1]->_v; } void protect() { null = new Tree(); null->ch[0] = null->ch[1] = null; null->Num = 0; } void insert(Tree *&o, int l, int r) { int mid = (l+r)/2; if(o == null) { o = &Node[tot++]; o->ch[0] = o->ch[1] = null; o->_l = l; o->_r = r; o->mid = (l+r)/2; } if(l == r) { o->_v = v; return; } if(_k <= mid) insert(o->ch[0], l, mid); else insert(o->ch[1], mid+1, r); o->maintain(); o->Num = o->ch[1]->Num + o->ch[0]->Num; } Tree* Build(int n, long long *a) { protect(); Root = null; for(int i = 1; i <= n; i++) _k = i, v = a[i], insert(Root, 1, n); return Root; } long long query(Tree *o) { long long ans = 0; o->update(); if(_L <= o->_l && o->_r <= _R) return o->_v; if(_L <= o->mid) ans += query(o->ch[0]); if(_R > o->mid) ans += query(o->ch[1]); return ans; } long long Query(int L, int R) { _L = L; _R = R; return query(Root); } void change(Tree *o) { o->update(); if(_L <= o->_l && o->_r <= _R) { o->label += v; o->update(); return; } if(_L <= o->mid) change(o->ch[0]); if(_R > o->mid) change(o->ch[1]); o->maintain(); } void Change(int L, int R, int V) { _L = L; _R = R; v = V; change(Root); } }; using namespace seqtree; struct Data { int l, r, v; bool operator < (const Data &B) const { return v < B.v; } }A[Maxn]; int n, m, l, r; long long a[Maxn], ANS[Maxn]; int main() { cin.sync_with_stdio(false); cin>>n>>m; Build(m+1, a); for(int i = 0; i < n; i++) { cin>>A[i].l>>A[i].r; A[i].v = A[i].r - A[i].l + 1; } sort(A, A+n); int k = 0; for(int i = 1; i <= m; i++) { for(; A[k].v < i && k < n; k++) Change(A[k].l, A[k].r, 1); int ans = n - k; for(int j = i; j <= m; j += i) ans += Query(j, j); cout<<ans<<endl; } }