luogu7476苦涩
「C.E.L.U-02」苦涩
题目背景
回想起自己的过往的人生,YQH 觉得心中充满了苦涩。如果人生能再来一次,我一定会少做一些傻事,少真香几次,然后大胆地去追寻自己的爱。可惜没有这样一个机会了。
题目描述
在 YQH 的梦中,他看到自己过去的记忆正在不断浮现在自己脑中。这些记忆带给他的是满满的苦涩。他想要强行忘记一些来减轻自己的苦涩。
YQH 的脑中可以被分成 \(n\) 个片区,每个片区相当于一个存放记忆的可重集,初始为空。他将进行 \(m\) 次这三种操作:
操作 1:区间 \(l\sim r\) 的片区中都浮现了一个苦涩值为 \(k\) 的记忆。
操作 2:YQH 开始清理 \(l\sim r\) 片区的记忆。如果一个片区 \(k\in[l,r]\) 且 \(k\) 中苦涩值最大的记忆与 \(l\sim r\) 片区中苦涩值最大的记忆相等,则将这个苦涩值最大的记忆忘记。如果在同一个片区有多个相同的苦涩值最大的记忆,则只忘记一个。如果这些片区内没有记忆,则无视。
操作 3:YQH 想知道,\(l\sim r\) 片区中苦涩值最大的记忆的苦涩值是多少,如果不存在,输出-1
。
输入格式
第一行两个数,\(n,m\)。
接下来 \(m\) 行,第一个数代表操作种类 \(op\),对于操作 1,有三个数 \(l,r,k\),对于操作 2 或 3,有两个数 \(l,r\)。
输出格式
对于每个操作 3 输出一行,代表答案。
样例 #1
样例输入 #1
5 4
1 1 3 2
1 2 4 3
2 3 3
3 1 3
样例输出 #1
3
样例 #2
样例输入 #2
6 6
1 1 6 2
1 3 3 2
1 3 4 3
2 3 4
3 3 3
3 4 4
样例输出 #2
2
2
提示
样例解释
样例解释一
下面为各操作之后 YQH 的大脑的状态:
第一次操作:\(\{2\},\{2\},\{2\},\varnothing,\varnothing\)
第二次操作:\(\{2\},\{2,3\},\{2,3\},\{3\},\varnothing\)
第三次操作:\(\{2\},\{2,3\},\{2\},\{3\},\varnothing\)
第四次操作询问 区间 \(1\sim 3\) 的最大值,所以答案是 \(3\)。
样例解释二
下面为各操作之后 YQH 的大脑的状态:
第一次操作:\(\{2\},\{2\},\{2\},\{2\},\{2\},\{2\}\)
第二次操作:\(\{2\},\{2\},\{2,2\},\{2\},\{2\},\{2\}\)
第三次操作:\(\{2\},\{2\},\{2,2,3\},\{2,3\},\{2\},\{2\}\)
第四次操作:\(\{2\},\{2\},\{2,2\},\{2\},\{2\},\{2\}\)
第五次操作询问 \(3\) 的最大值,所以答案是 \(2\)。
第六次操作询问 \(4\) 的最大值,所以答案是 \(2\)。
数据范围
Subtask | n | m | 特殊性质 |
---|---|---|---|
\(1(10pts)\) | \(\leq10^3\) | \(\le10^3\) | \(\diagdown\) |
\(2(20pts)\) | \(\leq5\times10^4\) | \(\leq5\times10^4\) | 没有操作 2 |
\(3(10pts)\) | \(\leq5\times10^4\) | \(\leq5\times10^4\) | 操作 2 中 \(l=r\) |
\(4(20pts)\) | \(\leq5\times10^4\) | \(\leq5\times10^4\) | \(\diagdown\) |
\(5(20pts)\) | \(\leq2\times10^5\) | \(\leq2\times10^5\) | 操作 2 中 \(l=r\) |
\(6(20pts)\) | \(\leq2\times10^5\) | \(\leq2\times10^5\) | \(\diagdown\) |
对于 \(100\%\) 的数据,\(n,m\le2\times10^5,k\le10^9\)
这个题目折腾了一天多!!!
明显是线段树,每个节点里面套一个堆!
刚开始想下传标记,想要下传中快速合并,就用左偏树呗!可是,写到合并了,发现当当前的的堆和左孩子合并后就没了,那谁和有孩子合并,又不能复制一个。后来一想,既然不能下传,干脆普通堆算了。可是还是下穿了一点东西,就是当堆顶的元素等于要清除的元素时,只能下传到包含的点再清楚。当然,这个只需要堆里面的插入删除就好了,logn!最后还错了一个更新点,调了一会儿就过了!
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,m;
struct node
{
int mx;
priority_queue<int>q;
}xds[maxn<<3];
void insert(int cur,int l,int r,int lq,int rq,int x)
{
if(lq<=l&&r<=rq)
{
xds[cur].q.push(x);
xds[cur].mx=max(xds[cur].mx,x);
return;
}
int mid=(l+r)>>1;
if(lq<=mid)insert(cur<<1,l,mid,lq,rq,x);
if(mid<rq)insert(cur<<1|1,mid+1,r,lq,rq,x);
xds[cur].mx=max(xds[cur].q.top(),max(xds[cur<<1].mx,xds[cur<<1|1].mx));
}
int query(int cur,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
{
return xds[cur].mx;
}
int mid=(l+r)>>1,ans=xds[cur].q.top();
if(ql<=mid)ans=max(ans,query(cur<<1,l,mid,ql,qr));
if(mid<qr)ans=max(ans,query(cur<<1|1,mid+1,r,ql,qr));
return ans;
}
void down(int cur)
{
int x=xds[cur].q.top();
xds[cur].q.pop();
xds[cur<<1].mx=max(xds[cur<<1].mx,x);
xds[cur<<1|1].mx=max(xds[cur<<1|1].mx,x);
xds[cur<<1].q.push(x);
xds[cur<<1|1].q.push(x);
}
void clear(int cur,int l,int r,int ql,int qr,int x)
{
if(l>r)return ;
if(xds[cur].q.top()>x)return;
if(xds[cur].mx<x)return;
if(ql<=l&&r<=qr)
{
if(xds[cur].mx==x)
{
if(xds[cur].q.top()==x)
{
xds[cur].q.pop();
xds[cur].mx=max(xds[cur].q.top(),max(xds[cur<<1].mx,xds[cur<<1|1].mx));
return ;
}
}
}
int mid=(l+r)>>1;
if(xds[cur].q.top()==x)down(cur);
if(ql<=mid)clear(cur<<1,l,mid,ql,qr,x);
if(mid<qr)clear(cur<<1|1,mid+1,r,ql,qr,x);
xds[cur].mx=max(xds[cur].q.top(),max(xds[cur<<1].mx,xds[cur<<1|1].mx));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<=(n<<3);++i)xds[i].mx=-1,xds[i].q.push(-1);
while(m--)
{
int opt,l,r,x;
scanf("%d%d%d",&opt,&l,&r);
if(opt==1)
{
scanf("%d",&x);
insert(1,1,n,l,r,x);
}
else if(opt==2)
{
int x=query(1,1,n,l,r);
if(x!=-1)clear(1,1,n,l,r,x);
}
else
{
int mx=query(1,1,n,l,r);
printf("%d\n",mx);
}
}
return 0;
}