[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;
}
$$\texttt{Dirty Deeds Done Dirt Cheap}$$