社区讨论
一点疑问 关于离散化
P5906【模板】回滚莫队&不删除莫队参与者 3已保存回复 4
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @mhji7rtp
- 此快照首次捕获于
- 2025/11/04 02:59 4 个月前
- 此快照最后确认于
- 2025/11/04 02:59 4 个月前
C
# include <bits/stdc++.h>
using namespace std;
struct query
{
int l;
int r;
int id; // 原本的编号
int num; // 左端点所在块编号
};
bool rule(query a,query b)
{
if (a.num != b.num)
{
return a.num < b.num;
}
return a.r < b.r;
}
struct query q[200005];
long long arr[200005];
long long tmp[200005];
int l[200005]; // 数字 i 最左边的是 l[i]
int r[200005]; // 数字 i 最右边的是 r[i]
int ans[200005];
int chk[200005];
int tmpl[200005];
int tmpr[200005];
int sta[50000005];
int tot;
int main (void)
{
int n;
scanf ("%d",&n);
for (int i=1;i<=n;i++)
{
scanf ("%d",&arr[i]);
tmp[i] = arr[i];
}
sort(tmp+1,tmp+1+n);
for (int i=1;i<=n;i++)
{
arr[i] = lower_bound(tmp+1,tmp+1+n,arr[i]) - tmp;
printf ("%d ",arr[i]);
tmpl[i]= l[i] = INT_MAX;
}
int siz = (int)sqrt(n);
int bln = n / siz; // 块数
int m;
scanf ("%d",&m);
for (int i=1;i<=m;i++)
{
scanf ("%d %d",&q[i].l,&q[i].r);
q[i].num = q[i].l / siz;
q[i].id = i;
// printf ("\n%d:%d\n",i,q[i].num);
}
sort(q+1,q+m+1,rule);
int ll = siz,rr = siz-1;
int tans1=0;
for (int i=1;i<=m;i++)
{
// printf("%d %d\n",q[i].l,q[i].r);
if (q[i].num != q[i-1].num)
{ // 新的区间
ll = (q[i].num+1)*siz;
rr = (q[i].num+1)*siz - 1;
for (int j=1;j<=n;j++) // 重置区间统计的状态
{
l[i] = INT_MAX;
r[i] = 0;
chk[i] = 0;
}
tans1=0;
}
int tl = q[i].l,tr = q[i].r;
if (tl/siz == tr/siz) // tl与tr在同一块中
{
for (int j=tl;j<=tr;j++) // 暴力统计
{
int x = arr[j];
r[x] = max(r[x],j);
l[x] = min(l[x],j);
tans1 = max(r[x]-l[x],tans1);
sta[++tot] = x; // 操作入栈
}
ans[q[i].id] = tans1;
while (tot--) //不要影响下面的操作
{
l[sta[tot]] = INT_MAX;
r[sta[tot]] = 0;
}
// printf ("1:%d %d\n",tl,tr);
tans1=0;
}
else
{
// printf ("2: r: %d->%d\n",rr,tr);
while (rr < tr) // 向右扩展
{
rr++;
int x = arr[rr];
r[x] = max(r[x],rr);
l[x] = min(l[x],rr);
// printf ("向右 数字:%d 位置:%d : l:%d r:%d\n",x,rr,l[x],r[x]);
tans1 = max(r[x]-l[x],tans1);
chk[x]++;
}
int tans2 = tans1; // 最终答案
// printf ("l: %d->%d\n",ll,tl);
while (tl < ll) // 从右端点向左扩展
{
ll--;
int x = arr[ll];
tmpr[x] = max(tmpr[x],ll);
tmpl[x] = min(tmpl[x],ll);
if (!chk[x]) tans2 = max(tmpr[x] - tmpl[x],tans2); // 右端点区间没有这个值
else tans2 = max(max(tmpr[x],r[x])-min(l[x],tmpl[x]),tans2);
sta[++tot] = x; // 操作入栈
chk[x]++;
// printf ("向左 数字:%d 位置: %d l,r,tmpl,tmpr : %d %d %d %d\n",x,ll,l[x],r[x],tmpl[x],tmpr[x]);
}
while (tot--) // 回滚 撤销出栈
{
tmpl[sta[tot]] = INT_MAX;
tmpr[sta[tot]] = 0;
chk[sta[tot]]--;
}
ans[q[i].id] = tans2; // 最终答案
ll = (q[i].num+1)*siz; // 将莫队区间重置到右端点
}
// printf ("\n");
}
/*for (int i=1;i<=m;i++)
{
printf ("%d\n",ans[i]);
}
*/
return 0;
}
我这份代码中的离散化无法通过此题,使用第一篇题解的离散化可以解决,这两者有什么区别吗?
回复
共 4 条回复,欢迎继续交流。
正在加载回复...