题目大意
给出一个序列,每次操作给出参数l,r,v,就是将区间[l,r]可能跨过n里面进行一次操作。
题解
先考虑l=1,r=n的部分分,
显然每次一个v进入这个区间,然后最大值出来,因为每次都是操作一个区间,那么这个区间里面的所有元素顺序都是不要记录的。
根据这个思路,可以想到分块,设块大小为K,
对于每一个块,用一个set维护这一个块里面元素的大小关系,还有一个堆来维护这个块的修改标记。
对于一个操作,首尾的块通过堆里面的修改标记,直接重构整一个块。然后中间跨过去的块就直接将v扔进去,然后把最大值取出来,在修改标记上面标记一下。
重构一个块就是顺序枚举每一个位置,每次将堆里面最小的元素拿出来,如果比当前这个位置小就见当前位置跟这个元素进行替换。
块大小
K
=
n
K=\sqrt n
K=n
code
#include <cstdio>
#include <queue>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <set>
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
int w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(int x){if(x>9) write(x/10);P(x%10+'0');}
const int N=400003;
int n,nn,w,m,l,r,v,a[N],st,fi,t;
priority_queue <int> d[N];
multiset<int>q[N];
multiset<int>::iterator id;
void work(int l,int r)
{
int ins;
st=(l-1)/nn+1;fi=(r-1)/nn+1;
if(st==fi)
{
if(!d[st].empty())
{
t=-d[st].top();
for(int j=st*nn-nn+1;j<=st*nn;j++)
if(t<a[j])d[st].pop(),d[st].push(-a[j]),a[j]=t,t=-d[st].top();
}
for(;!d[st].empty();d[st].pop());
ins=v;
for(int j=l;j<=r;j++)
if(a[j]>v)swap(a[j],v);
if(ins^v)q[st].erase(q[st].find(v)),q[st].insert(ins);
}
else
{
if(!d[st].empty())
{
t=-d[st].top();
for(int j=st*nn-nn+1;j<=st*nn;j++)
if(t<a[j])d[st].pop(),d[st].push(-a[j]),a[j]=t,t=-d[st].top();
}
ins=v;
for(int j=l;j<=st*nn;j++)
if(a[j]>v)swap(a[j],v);
if(ins^v)q[st].erase(q[st].find(v)),q[st].insert(ins);
for(;!d[st].empty();d[st].pop());
for(int j=st+1;j<fi;j++)
{
id=q[j].end();id--;t=*id;
if(t>v)d[j].push(-v),q[j].erase(id),q[j].insert(v),v=t;
}
if(!d[fi].empty())
{
t=-d[fi].top();
for(int j=fi*nn-nn+1;j<=fi*nn;j++)
if(t<a[j])d[fi].pop(),d[fi].push(-a[j]),a[j]=t,t=-d[fi].top();
}
ins=v;
for(int j=fi*nn-nn+1;j<=r;j++)
if(a[j]>v)swap(a[j],v);
if(ins^v)q[fi].erase(q[fi].find(v)),q[fi].insert(ins);
for(;!d[fi].empty();d[fi].pop());
}
}
int main()
{
read(n);read(m);nn=sqrt(n);w=n/nn+(n%nn?1:0);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1;i<=w;i++)l=i*nn-nn+1,r=min(i*nn,n),q[i].insert(a+l,a+r+1);
for(int i=1;i<=m;i++)
{
read(l);read(r);read(v);
if(l<=r)work(l,r);
else work(l,n),work(1,r);
write(v),P('\n');
}
return 0;
}