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

 

posted @ 2017-01-29 16:17  Saurus  阅读(197)  评论(0编辑  收藏  举报