想一下传送带 (233)
我记得我和 lh 说了可以对于一个整块把一堆操作放在一起处理
暴力匹配是 O ( n q ) O(nq) O(nq) 的。
但是如果加一个优先队列呢?
那你就可以在 O ( B l o g Q i ) O(BlogQ_i) O(BlogQi) 的时间内复原这个块 (其中 Q i Q_i Qi 是对这个整块操作的次数)
你再算一下重构的次数和每次操作 insert 的那些点不就完了嘛。
#include<bits/stdc++.h>
#define db double
#define ll long long
#define mkp make_pair
#define pii pair<int,int>
#define inf 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
const int Maxn=4e5+5;
const int Maxm=630;
const int mod=23333333;
inline int read() {
int x=0,f=1; char c=getchar();
while(c<'0'||c>'9') {
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x;
}
int n,block,m,L[Maxn],R[Maxn],a[Maxn],bl[Maxn];
priority_queue<int> q[Maxn/Maxm+5];
priority_queue<int,vector<int>,greater<int>> q2[Maxn/Maxm+5];
void merge(int l) {
while(q[l].size()) q[l].pop();
for(int i=L[l];i<=R[l];i++) {
q[l].push(a[i]);
}
}
//人去选菜 (选最小的那个)
void split(int l) {
for(int i=L[l];i<=R[l];i++) {
if(q2[l].size()) {
int tmp=q2[l].top();
if(tmp<a[i]) {
q2[l].pop();
q2[l].push(a[i]);
a[i]=tmp;
}
}
}
while(q2[l].size()) q2[l].pop();
merge(l);
}
int solve(int l,int r,int x) {
int le=bl[l],ri=bl[r];
if(le==ri) {
split(le);
for(int i=l;i<=r;i++) {
if(a[i]>x) {
swap(a[i],x);
}
}
merge(le);
}
else {
split(le);
split(ri);
for(int i=l;i<=R[le];i++) {
if(a[i]>x) {
swap(a[i],x);
}
}
//来康一康怎么给整块打标记
for(int i=le+1;i<=ri-1;i++) {
int tmp=q[i].top();
if(tmp>x) {
q[i].pop();
q[i].push(x);
q2[i].push(x);
x=tmp;
}
}
for(int i=L[ri];i<=r;i++) {
if(a[i]>x) {
swap(a[i],x);
}
}
merge(le);
merge(ri);
}
return x;
}
int main() {
// freopen("data.in","r",stdin);
n=read(),m=read();
block=sqrt(n);
for(int i=1;i<=n;i++) {
bl[i]=(i-1)/block+1;
}
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=(n-1)/block+1;i++) {
L[i]=(i-1)*block+1;
R[i]=min(n,i*block);
merge(i);
}
// for(int i=1;i<=(n-1)/block+1;i++) {
// printf("%d\n",q[i].size());
// }
for(int i=1;i<=m;i++) {
int l=read(),r=read(),x=read();
if(l<=r) {
printf("%d\n",solve(l,r,x));
}
else {
printf("%d\n",solve(1,r,solve(l,n,x)));
}
// for(int j=1;j<=(n-1)/block+1;j++) {
// split(j);
// }
// for(int j=1;j<=n;j++) {
// printf("%d ",a[j]);
// }
// printf("\n");
}
}