BZOJ4552 [Tjoi2016&Heoi2016]排序
题目描述
题目分析
对于一个排列直接找明显不现实,考虑将其转化成一个比较容易计算的排列上去。
明显对于一个(01)序列,我们进行如上操作是很容易的,首先计算区间内(1)的个数(cnt),然后以升序排列为例,我们将([L,R-cnt])的部分区间覆盖为(0),将([R-cnt+1,R])的部分区间覆盖为(1)就可以了。
发现只有一组询问,考虑二分。
可以二分一个数,然后将比这个数小的置为(0),其余的置为(1)。然后对这个数列进行(check)。如果最后这个位置上是(1)就说明答案要更大,否则更小。
是代码呢
#include <bits/stdc++.h>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
const int MAXN=2e5+7;
int sum[MAXN],tag[MAXN],b[MAXN],n,m,Q,a[MAXN],ans;
struct po{
int opt,l,r;
}q[MAXN];
inline void pushup(int rt){sum[rt]=sum[ls]+sum[rs];}
inline void pushdown(int l,int r,int rt)
{
if(tag[rt]!=-1){
sum[ls]=(mid-l+1)*tag[rt];
sum[rs]=(r-mid)*tag[rt];
tag[ls]=tag[rs]=tag[rt];
tag[rt]=-1;
}
}
inline void build(int l,int r,int rt)
{
tag[rt]=-1;
if(l==r){
sum[rt]=b[l];return;
}
build(l,mid,ls);build(mid+1,r,rs);
pushup(rt);
}
inline void update(int L,int R,int k,int l,int r,int rt){
if(L<=l&&r<=R){
sum[rt]=(r-l+1)*k;tag[rt]=k;
return;
}
pushdown(l,r,rt);
if(L<=mid) update(L,R,k,l,mid,ls);
if(R>mid) update(L,R,k,mid+1,r,rs);
pushup(rt);
}
inline int query(int L,int R,int l,int r,int rt)
{
if(l>R||r<L) return 0;
pushdown(l,r,rt);
if(L<=l&&r<=R) return sum[rt];
return query(L,R,l,mid,ls)+query(L,R,mid+1,r,rs);
}
inline int check(int x)
{
for(int i=1;i<=n;i++) b[i]=(a[i]>=x)?1:0;
build(1,n,1);
for(int i=1;i<=m;i++){
int cnt=query(q[i].l,q[i].r,1,n,1);
// cout<<q[i].l<<" "<<q[i].r<<endl;
if(q[i].opt==0){
if(cnt!=q[i].r-q[i].l+1)update(q[i].l,q[i].r-cnt,0,1,n,1);
if(cnt>0)update(q[i].r-cnt+1,q[i].r,1,1,n,1);
} else {
if(cnt>0)update(q[i].l,q[i].l+cnt-1,1,1,n,1);
if(cnt!=q[i].r-q[i].l+1)update(q[i].l+cnt,q[i].r,0,1,n,1);
}
}
int d=query(Q,Q,1,n,1);
return d;
}
inline int read()
{
int x=0,c=1;
char ch=' ';
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
while(ch=='-')c*=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*c;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++) {int opt=read(),x=read(),y=read();q[i]=(po){opt,x,y};}
Q=read();
int l=1,r=n;
while(l<=r){
if(check(mid))l=mid+1;
else r=mid-1,ans=mid;
}
cout<<l-1;
}