题解 P2930 【[USACO09HOL]假期绘画Holiday Painting】
线段树? 不用吧
还是要分成C个序列来处理\ 我的思路是将每个序列分成k个颜色相同的块,然后每个块都算一下有几个满足要求就行了。\ 具体就是用队列,存三个变量l,r,g,分别表示这个块的左端点,右端点和颜色,每次询问就过一遍,将要加入的一段颜色加入,再分类讨论原有块和加入块的位置关系保证一个点不出现在两个块里就行了。\ ps:为了提升运算的速度,要将队列中相邻的颜色一样的块合并。\ 时间复杂度:俺也不知道,反正过了。\ 代码略长(反正分类讨论写了一种情况就可以复制粘贴了)
#include<bits/stdc++.h>
using namespace std;
int R,C,q,sum[16][50010],que[16][2][50010][3],len[16];
int main()
{
scanf("%d%d%d",&R,&C,&q);
for(int i=1;i<=R;i++)
{
getchar();
for(int j=1;j<=C;j++)
{
bool tmp=getchar()-'0';
sum[j][i]=sum[j][i-1]+tmp;
}
}
for(int i=1;i<=C;i++)
{
que[i][0][1][0]=1;
que[i][0][1][1]=R;
que[i][0][1][2]=0;
len[i]=1;
}//一开始只有一个块
for(int i=1;i<=q;i++)
{
bool nw=i%2;
int x1,x2,y1,y2,kd;
scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&kd);
for(int j=1;j<y1;j++)
{
for(int e=1;e<=len[j];e++)
{
que[j][nw][e][0]=que[j][!nw][e][0];
que[j][nw][e][1]=que[j][!nw][e][1];
que[j][nw][e][2]=que[j][!nw][e][2];
}
}
for(int j=y2+1;j<=C;j++)
{
for(int e=1;e<=len[j];e++)
{
que[j][nw][e][0]=que[j][!nw][e][0];
que[j][nw][e][1]=que[j][!nw][e][1];
que[j][nw][e][2]=que[j][!nw][e][2];
}
}
for(int j=y1;j<=y2;j++)
{
int tmp=0;
for(int e=1;e<=len[j];e++)
{
bool hv=0;
int l=que[j][!nw][e][0],r=que[j][!nw][e][1];
if(l>=x1&&r<=x2) hv=1;//被要加入的块压住了就可以不管了
if(x1==l)
{
hv=1;
if(tmp!=0&&que[j][nw][tmp][2]==kd) que[j][nw][tmp][1]=x2;
else
{
que[j][nw][++tmp][2]=kd;
que[j][nw][tmp][1]=x2;
que[j][nw][tmp][0]=x1;
}
}
if(que[j][!nw][e][1]>=x1&&que[j][!nw][e][0]<x1)
{
hv=1;
que[j][nw][++tmp][0]=que[j][!nw][e][0];
que[j][nw][tmp][1]=x1-1;
que[j][nw][tmp][2]=que[j][!nw][e][2];
if(tmp!=0&&que[j][nw][tmp][2]==kd) que[j][nw][tmp][1]=x2;
else
{
que[j][nw][++tmp][2]=kd;
que[j][nw][tmp][1]=x2;
que[j][nw][tmp][0]=x1;
}
}
if(que[j][!nw][e][1]>x2&&que[j][!nw][e][0]<=x2)
{
if(tmp!=0&&que[j][nw][tmp][2]==que[j][!nw][e][2])
{
que[j][nw][tmp][1]=r;
continue;
}
que[j][nw][++tmp][0]=x2+1;
que[j][nw][tmp][1]=r;
que[j][nw][tmp][2]=que[j][!nw][e][2];
continue;
}
if(hv) continue;//以上是分类讨论
if(tmp!=0&&que[j][!nw][e][2]==que[j][nw][tmp][2]) que[j][nw][tmp][1]=r;
else
{
que[j][nw][++tmp][0]=l;
que[j][nw][tmp][1]=r;
que[j][nw][tmp][2]=que[j][!nw][e][2];
}
}
len[j]=tmp;
}
int ans=0;
for(int j=1;j<=C;j++)
{
for(int e=1;e<=len[j];e++)
{
int tmp=sum[j][que[j][nw][e][1]]-sum[j][que[j][nw][e][0]-1];
if(que[j][nw][e][2]) ans+=tmp;
else ans+=(que[j][nw][e][1]-que[j][nw][e][0]+1-tmp);
}
}
printf("%d\n",ans);
}
}