一、题目
二、解法
其实本题的突破口在只有一个询问上,因为没有排序算法能达到
O
(
log
n
)
O(\log n)
O(logn)。
考虑
log
\log
log的复杂度排序,发现它只能对
01
01
01串进行排序,我们尝试把问题转化为
01
01
01串的排序。
如果我们有一个分界值
x
x
x,那么小于
x
x
x的是
0
0
0,否则是
1
1
1,排序可以用线段树实现,维护
0
0
0的个数,支持区间赋值。这样我们可以得到一个关于大小的描述,我们看最后
q
q
q位是否为
1
1
1,如果为
1
1
1,就可以确定
a
[
q
]
≤
x
a[q]\leq x
a[q]≤x,所以我们二分
x
x
x,找到一个能使
q
q
q位为
1
1
1的最大的
x
x
x,即为答案。
时间复杂度
O
(
n
log
2
n
)
O(n\log^2 n)
O(nlog2n)。
#include <cstdio>
#define Len(i) (tr[i].r-tr[i].l+1)
const int MAXN = 100005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^'0'),c=getchar();
return x*flag;
}
int n,m,q,ans,a[MAXN];
struct node
{
int op,l,r;
}s[MAXN];
struct tree
{
int l,r,sum,lazy;//1->0 2->1
}tr[MAXN*4];
void build(int i,int l,int r)
{
tr[i]=tree{l,r,0,0};
if(l==r) return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void down(int i)
{
if(tr[i].lazy==1)
{
tr[i<<1].sum=Len(i<<1),tr[i<<1].lazy=1;
tr[i<<1|1].sum=Len(i<<1|1),tr[i<<1|1].lazy=1;
}
else
{
tr[i<<1].sum=0,tr[i<<1].lazy=2;
tr[i<<1|1].sum=0,tr[i<<1|1].lazy=2;
}
tr[i].lazy=0;
}
void updata(int i,int l,int r,int t)
{
if(l>r || tr[i].l>r || tr[i].r<l)
return ;
if(l<=tr[i].l && tr[i].r<=r)
{
if(t==0) tr[i].sum=Len(i),tr[i].lazy=1;
else tr[i].sum=0,tr[i].lazy=2;
return ;
}
if(tr[i].lazy) down(i);
updata(i<<1,l,r,t);
updata(i<<1|1,l,r,t);
tr[i].sum=tr[i<<1].sum+tr[i<<1|1].sum;
}
int query(int i,int l,int r)
{
if(tr[i].l>r || tr[i].r<l)
return 0;
if(l<=tr[i].l && tr[i].r<=r)
return tr[i].sum;
if(tr[i].lazy) down(i);
return query(i<<1,l,r)+query(i<<1|1,l,r);
}
bool check(int x)
{
build(1,1,n);
for(int i=1;i<=n;i++)
updata(1,i,i,a[i]>=x);
for(int i=1;i<=m;i++)
{
int op=s[i].op,l=s[i].l,r=s[i].r;
int t=query(1,l,r);
if(op==0)
{
updata(1,l,l+t-1,0);
updata(1,l+t,r,1);
}
else
{
updata(1,l,r-t,1);
updata(1,r-t+1,r,0);
}
}
return query(1,q,q)==0;
}
void dich(int l,int r)
{
if(l>r) return ;
int mid=(l+r)>>1;
if(check(mid))
{
ans=mid;
dich(mid+1,r);
}
else
dich(l,mid-1);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=m;i++)
s[i]=node{read(),read(),read()};
q=read();
dich(1,n);
printf("%d\n",ans);
}
其实这道题暴力桶排然后开 O 2 O2 O2也能过。