http://ac.jobdu.com/problem.php?pid=1496
超时原因:
正常模拟,极端情况下,第k+1次操作对第k次操作的数字实现了全覆盖,则第k次操作对于最终结果全无意义
改善:逆向操作,先进行第k次操作,则第k-1次操作时,为0的数字(后续操作没有再覆盖操作)才进行修改
某大牛使用了next数组,每次修改数字后,保存当前数字a[i]右边第一个为0点的坐标
若不用修改,遍历坐标变为next [ i ] ,再看遍历坐标是否超出当前操作的范围,大大节省了这个范围内的无用操作时间
代码如下:
#include <stdio.h>
#include <string.h>
struct E
{
int l,r;
}buf[100005]; //保存m次操作的左右下标
int a[1000005]; //保存长度为n的序列
int next[1000005];
int main()
{freopen("D:\\1.txt","r",stdin);
int i,j,l,r,n,m;
while (scanf("%d%d",&n,&m)!=EOF)
{
for (i=1;i<=n;i++)
{
a[i]=0;
next[i]=i+1; //当前数字a[i]右边第一个为0点的坐标
}
for (i=1;i<=m;i++)
{
scanf("%d%d",&buf[i].l,&buf[i].r);
}
for (i=m;i>=1;i--) //m次操作,通过使用next,减少了很多不必要操作
{
l=buf[i].l;
r=buf[i].r;
for (j=l;j<=r;)
{
if (a[j]==0)
{
a[j]=i;
}
int tmp=next[j]; //下次操作的坐标
next[j]=next[r];
j=tmp;
}
}
i=1;
int max=1,k=1;
while (i<=n)
{
if (a[i]==0)
{
i++;
continue;
}
k=1;
while (a[i]==a[i+k]&&i+k<=n)
{
k++;
}
if (k>max)
{
max=k;
}
i=i+k;
}
printf("%d\n",max);
}
return 0;
}