题目链接
题解
扫描线,先将每个操作按照y轴排序,考虑水从下面淹到上面。
对于挡板被截断的情况:并查集合并左侧和右侧的格子。
对于要求没有水的情况:如果水不淹到上面,那么它一定会被满足。
对于要求有水的情况:直接把下面的全淹了,再来更新答案。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn=100000;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
struct data
{
int op,x,y;
data(int op_=0,int x_=0,int y_=0)
{
op=op_;
x=x_;
y=y_;
}
bool operator <(const data &other) const
{
if(y==other.y)
{
return op<other.op;
}
return y<other.y;
}
};
namespace dsu
{
int fa[maxn+10];
inline int clear()
{
memset(fa,0,sizeof fa);
return 0;
}
int find(int x)
{
return fa[x]?fa[x]=find(fa[x]):x;
}
}
data d[maxn*2+10];
int f[maxn+10],ans[maxn+10],cnt,t,n,m,lastans;
int main()
{
t=read();
while(t--)
{
cnt=0;
memset(f,0,sizeof f);
memset(ans,0,sizeof f);
lastans=0;
dsu::clear();
n=read();
m=read();
for(int i=1; i<n; ++i)
{
int h=read();
d[++cnt]=data(-1,i,h);
}
while(m--)
{
int x=read(),y=read(),op=read();
d[++cnt]=data(op,x,y);
}
std::sort(d+1,d+cnt+1);
for(int i=1; i<=cnt; ++i)
{
if(d[i].op==-1)
{
int x=dsu::find(d[i].x),y=dsu::find(d[i].x+1);
dsu::fa[y]=x;
f[x]+=f[y];
ans[x]+=ans[y];
lastans=std::max(lastans,ans[x]);
}
else if(d[i].op==0)
{
lastans=std::max(lastans,++ans[dsu::find(d[i].x)]);
}
else
{
int x=dsu::find(d[i].x);
lastans=std::max(lastans,ans[x]=std::max(ans[x],++f[x]));
}
}
printf("%d\n",lastans);
}
return 0;
}