离线算法理论上要用线段树,但我不太想打所以写了分块……明天还没人就写平衡树了
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10,blen=sqrt(maxn)+10;
int num[maxn];
int usen[maxn],cnt[blen][2],setn[blen];
int n,m,q;
inline int getb(int x)
{
return (x-1)/blen+1;
}
void pushdown(int num)
{
if(setn[num]==-1) return;
for(int i=(num-1)*blen+1;i<=min(n,num*blen);i++)
usen[i]=setn[num];
setn[num]=-1;
}
void draw(int l,int r,int num)
{
int bl=getb(l),br=getb(r);
pushdown(bl);pushdown(br);
for(int i=l;i<=min(r,bl*blen);i++)
{
cnt[bl][usen[i]]--;
usen[i]=num;
cnt[bl][num]++;
}
if(bl!=br)
{
for(int i=(br-1)*blen+1;i<=r;i++)
{
cnt[br][usen[i]]--;
usen[i]=num;
cnt[br][num]++;
}
for(int i=bl+1;i<=br-1;i++)
{
setn[i]=num;
cnt[i][!num]=0,cnt[i][num]=blen;
}
}
}
void sort1(int l,int r,int opt)
{
int bl=getb(l),br=getb(r);
int cnt1=0,cnt0=0;
pushdown(bl),pushdown(br);
for(int i=l;i<=min(r,bl*blen);i++)
if(usen[i]==1) cnt1++;
else cnt0++;
if(bl!=br)
{
for(int i=(br-1)*blen+1;i<=r;i++)
if(usen[i]==1) cnt1++;
else cnt0++;
for(int i=bl+1;i<=br-1;i++)
cnt1+=cnt[i][1],cnt0+=cnt[i][0];
}
if(opt==1) draw(l,l+cnt1-1,1),draw(l+cnt1,r,0);
else draw(l,l+cnt0-1,0),draw(l+cnt0,r,1);
}
int cao[maxn][4];
bool p(int x)
{
for(int i=1;i<=getb(n);i++)
{
cnt[i][0]=cnt[i][1]=0;
setn[i]=-1;
}
for(int i=1;i<=n;i++)
{
if(num[i]>=x) usen[i]=1;
else usen[i]=0;
cnt[getb(i)][usen[i]]++;
}
for(int i=1;i<=m;i++)
{
int opt=cao[i][1],l=cao[i][2],r=cao[i][3];
sort1(l,r,opt);
}
pushdown(getb(q));
return usen[q];
}
int ask(int l,int r)
{
int ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(p(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
return ans;
}
inline int read()
{
int r=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){r=r*10+c-'0';c=getchar();}
return r*f;
}
int main()
{
//cin>>n>>m;
n=read();m=read();
for(int i=1;i<=n;i++) num[i]=read();
for(int i=1;i<=m;i++)
cao[i][1]=read(),cao[i][2]=read(),cao[i][3]=read();
cin>>q;
cout<<ask(1,n);
return 0;
}
/*
1 6 2 5 3 4
6 5 2 1 3 4
6 5
*/