[CERC2017]Buffalo Barricades

我们对于每头牛,找到最后建出图中 包含自己的最近的 一个栅栏点,并且将其归属到这个栅栏作为贡献。

然后分析过样例可以发现,有些栅栏是有 包含关系 的,具体的,需满足 \(x_i>x_j,y_i>y_j,t_i<t_j\),此时栅栏 \(i\) 包含栅栏 \(j\)

这个东西单 log 只能满足其中两个条件,并不能保证时间之间的关系。但是啊,我们运用并查集,最后算取答案的时候,按顺序建边,就可以做到这个事情。

具体的,如果连向的是 \(t\) 比自己大的,能保证这个点的答案已经算好了,我们不会将自己的影响作用在对方身上,但是根据并查集还是可以将这部分影响向后传而不会中断。

\[\texttt{El Psy Congroo} \]

int main()
{
    int i,j,k;
    for(i=1,n=rin();i<=n;i++)a[i].x=rin(),a[i].y=rin(),a[i].num=i;
    for(i=1,j=n+1,m=rin();i<=m;i++,j++)a[j].x=rin(),a[j].y=rin(),a[j].num=j;
    sort(a+1,a+n+m+1,myru_x);
    for(i=1,k=n+m;i<=k;i=j){nam++;for(j=i+1;j<=k&&a[j].x==a[i].x;j++)a[j].x=nam;a[i].x=nam;}
    sort(a+1,a+n+m+1,myru_y);
    for(i=1;i<=k;i++)
    {
        zjj now;
        now.x=a[i].x;now.num=a[i].num-n;
        if(a[i].num<=n)
        {
            if(z.empty())continue;
            set<zjj>::iterator j=z.lower_bound(now);
            if(j!=z.end())cnt[j->num]++;
        }
        else
        {
            if(z.empty()){z.insert(now);continue;}
            set<zjj>::iterator j=z.lower_bound(now);
            for(;!z.empty();j=z.lower_bound(now))
            {
                if(j!=z.begin())j--;else break;
                if(j->num<now.num)break;
                z.erase(j);
                if(z.empty())break;
            }
            if(!z.empty()){j=z.upper_bound(now);if(j!=z.end())nxt[now.num]=j->num;}
            z.insert(now);
        }
    }
    for(i=1;i<=m;i++)f[i]=i;
    for(i=m;i>=1;i--)
    {
        ans[i]=cnt[find(i)];
        if(nxt[i])
        {
            int x=find(i),y=find(nxt[i]);
            f[x]=y;
            cnt[y]+=cnt[x];
        }
    }
    for(i=1;i<=m;i++)printf("%d\n",ans[i]);
    return 0;
}
posted @ 2021-01-04 14:28  zjjws  阅读(117)  评论(0编辑  收藏  举报