Codeforces 780G Andryusha and Nervous Barriers

来源:互联网 发布:淘宝上回收手机可靠吗 编辑:程序博客网 时间:2024/06/13 04:54

现有一个宽w,高h的垂直空间,空间中有n个屏障,现在可以从h+1的高度垂直扔小球下去,如果小球遇到屏障且高度差不超过一个界限,小球就会分裂成两个继续下落,否则小球会穿过屏障。现在从每个单位宽度扔一个小球,求最终落到屏障上有多少小球。

容易想到一个dpi,j表示从(i,j)扔球得到的答案。考虑到n只有105,中间有大量空间是没有屏障的,我们重新考虑一个从下往上的dp。我们从一个点(x,y)扔球,其实我们只关心y之下,x最高的且不会被穿过的屏障是哪个。并且从每个屏障出发的答案是确定的,用dpi表示屏障i的答案,dpi = dpj+dpk,j,kli1,ri+1下去的屏障。那么我们开一个1w的线段树,维护每个坐标有用的屏障信息。从下到上地,在hi加入屏障i,在hi+si删除屏障i,这里可以方便地在线段树上使用set来维护。由此,我们得到一个O((n+w)log2w)的做法。

我们可以把从同一个位置扔出的小球看作一个集合,那么一个屏障最多会产生两个集合,且会至少减少一个集合,那么最多会有w+n个集合。我们对每个列坐标维护一个顺序栈,记录该列还存在的集合。从上往下的依次处理屏障,对于每个屏障,我们需要知道哪些集合会落在屏障上。我们建立一个线段树来维护区间中最低的集合,判断会落在屏障上后,将球的个数记录并退栈,否则该屏障处理结束。最后的答案就是栈中所有球的个数和。这样,我们得到了O((n+w)logw)的做法。

#include <bits/stdc++.h>using namespace std;const int maxn = 2e5 + 10;const int jyb = 1e9 + 7;struct node{    int l,r;    set<int>s;}t[maxn];int tot;struct Barriers{    int h,l,r,s;    bool operator < (const Barriers &b) const    {        if(s == b.s)            return h > b.h;        return s < b.s;     }}b[maxn];map<int,int>haha;int ans[maxn];int h,n,w;int hh,l,r,s;void build(int p,int l,int r){    if(l == r)        return;    int mid = (l + r) >> 1;    t[p].l = ++tot;    t[p].r = ++tot;    build(t[p].l,l,mid);    build(t[p].r,mid+1,r);}void change(int p,int l,int r,int L,int R,int h,int d){    if(L == l && R == r)    {        if(d == 1)            t[p].s.insert(h);        else            t[p].s.erase(h);        return;    }    int mid = (l + r) >> 1;    if(R <= mid)        change(t[p].l,l,mid,L,R,h,d);    else if(L > mid)        change(t[p].r,mid+1,r,L,R,h,d);    else    {        change(t[p].l,l,mid,L,mid,h,d);        change(t[p].r,mid+1,r,mid+1,R,h,d);    }}int query(int p,int l,int r,int pos){    int res = 0;    if(t[p].s.size() > 0)        res = *t[p].s.rbegin();    if(l == r)        return res;    int mid = (l + r) >> 1;    if(pos <= mid)        res = max(res,query(t[p].l,l,mid,pos));    else        res = max(res,query(t[p].r,mid+1,r,pos));    return res;}int main(){    cin >> h >> w >> n;    for(int i = 1; i <= n; i++)    {        scanf("%d%d%d%d",&hh,&l,&r,&s);        b[i*2-1].h = hh;        b[i*2-1].l = l;        b[i*2-1].r = r;        b[i*2-1].s = s + hh;        b[i*2].h = hh;        b[i*2].l = l;        b[i*2].r = r;        b[i*2].s = hh;        haha[hh] = i;    }    n <<= 1;    sort(b+1,b+1+n);    build(0,1,w);    ans[0] = 1;    for(int i = 1; i <= n; i++)    {        if(b[i].h != b[i].s)        {            if(b[i].s > h)                break;            change(0,1,w,b[i].l,b[i].r,b[i].h,-1);        }        else        {            int hl,hr;            if(b[i].l == 1)            {                hr = query(0,1,w,b[i].r+1);                ans[haha[b[i].h]] = 2 * ans[haha[hr]] % jyb;            }            else if(b[i].r == w)            {                hl = query(0,1,w,b[i].l-1);                ans[haha[b[i].h]] = 2 * ans[haha[hl]] % jyb;            }            else            {                hl = query(0,1,w,b[i].l-1);                hr = query(0,1,w,b[i].r+1);                ans[haha[b[i].h]] = (ans[haha[hl]] + ans[haha[hr]]) % jyb;            }            change(0,1,w,b[i].l,b[i].r,b[i].h,1);        }    }    int sum = 0;    for(int i = 1; i <= w; i++)    {        int h = query(0,1,w,i);        sum = (sum + ans[haha[h]]) % jyb;    }    printf("%d\n",sum);    return 0;}
#include <bits/stdc++.h>using namespace std;const int maxn = 1e5 + 10;const int jyb = 1e9 + 7;struct group{    int h,x;    group(int _h,int _x)    {        h = _h;        x = _x;    }};stack<group>s[maxn];struct node{    int l,r,x;}t[maxn << 1];int tot;struct Barriers{    int h,l,r,s;    bool operator < (const Barriers &b) const    {        return h > b.h;    }}b[maxn];int h,n,w;void build(int p,int l,int r){    if(l == r)    {        t[p].x = l;        return;    }    int mid = (l + r) >> 1;    t[p].l = ++tot;    t[p].r = ++tot;    build(t[p].l,l,mid);    build(t[p].r,mid+1,r);    t[p].x = t[t[p].l].x;}void del(int p,int l,int r,int pos){    int mid = (l + r) >> 1;    if(l == r)    {        s[pos].pop();        return;    }    int ls = t[p].l;    int rs = t[p].r;    if(pos <= mid)        del(ls,l,mid,pos);    else        del(rs,mid+1,r,pos);    int ll = t[ls].x;    int rr = t[rs].x;    if(s[rr].empty())        t[p].x = ll;    else if(s[ll].empty())        t[p].x = rr;    else        t[p].x = s[ll].top().h <= s[rr].top().h ? ll : rr;}void add(int p,int l,int r,int pos,const group g){    int mid = (l + r) >> 1;    if(l == r)    {        s[pos].push(g);        return;    }    int ls = t[p].l;    int rs = t[p].r;    if(pos <= mid)        add(ls,l,mid,pos,g);    else        add(rs,mid+1,r,pos,g);    int ll = t[ls].x;    int rr = t[rs].x;    if(s[rr].empty())        t[p].x = ll;    else if(s[ll].empty())        t[p].x = rr;    else        t[p].x = s[ll].top().h <= s[rr].top().h ? ll : rr;}int query(int p,int l,int r,int L,int R){    int mid = (l + r) >> 1;    if(l == L && r == R)        return t[p].x;    int ls = t[p].l;    int rs = t[p].r;    if(R <= mid)        return query(ls,l,mid,L,R);    else if(L > mid)        return query(rs,mid+1,r,L,R);    else    {        int ll = query(ls,l,mid,L,mid);        int rr = query(rs,mid+1,r,mid+1,R);        if(s[rr].empty())            return ll;        else if(s[ll].empty())            return rr;        else            return s[ll].top().h <= s[rr].top().h ? ll : rr;    }}int main(){    cin >> h >> w >> n;    for(int i = 1; i <= n; i++)        scanf("%d%d%d%d",&b[i].h,&b[i].l,&b[i].r,&b[i].s);    sort(b+1,b+1+n);    build(0,1,w);    for(int i = 1; i <= w; i++)        s[i].push(group(h+1,1));    for(int i = 1; i <= n; i++)    {        group p(b[i].h,0);        while(1)        {            int j = query(0,1,w,b[i].l,b[i].r);            if(s[j].empty())                break;            group tmp = s[j].top();            if(tmp.h > b[i].h + b[i].s)                break;            del(0,1,w,j);            p.x = (p.x + tmp.x) % jyb;;        }        if(b[i].l == 1)        {            p.x = (p.x + p.x) % jyb;            add(0,1,w,b[i].r+1,p);        }        else if(b[i].r == w)        {            p.x = (p.x + p.x) % jyb;            add(0,1,w,b[i].l-1,p);        }        else        {            add(0,1,w,b[i].l-1,p);            add(0,1,w,b[i].r+1,p);        }    }    int sum = 0;    for(int i = 1; i <= w; i++)        while(!s[i].empty())        {            sum = (sum + s[i].top().x) % jyb;            s[i].pop();        }    printf("%d\n",sum);    return 0;}