Luogu P2824 排序 题解 [ 紫 ] [ 线段树 ] [ 二分 ] [ adhoc ]
排序:二分线段树神仙好题。
trick
我们可以二分值域,然后把大于等于它的数标记成
运用到和这道题类似的 trick 的题还有这几道:最大战力 ,Median Pyramid Hard。
思路
知道这个 trick 之后这题就迎刃而解了。
因为这是个排列,所以我们直接二分
在 check 中,我们用线段树维护一个
最后 check 时查询线段树上的第
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
const int N=100005;
int n,m,a[N],ql[N],qr[N],qop[N],q;
struct node{
int l,r;
int sum1,sum0;
int tag;
}tr[4*N];
void pushup(node &p,node ls,node rs)
{
p.sum1=ls.sum1+rs.sum1;
p.sum0=ls.sum0+rs.sum0;
}
void pd(int p,int op)
{
node &t=tr[p];
if(op==0)
{
t.sum1=0;
t.sum0=t.r-t.l+1;
t.tag=0;
}
if(op==1)
{
t.sum0=0;
t.sum1=t.r-t.l+1;
t.tag=1;
}
}
void pushdown(int p)
{
if(tr[p].tag==0)
{
pd(lc,0);
pd(rc,0);
}
if(tr[p].tag==1)
{
pd(lc,1);
pd(rc,1);
}
tr[p].tag=-1;
}
void build(int p,int ln,int rn,int x)
{
tr[p]={ln,rn,a[ln]>=x,a[ln]<x,-1};
if(ln==rn)return;
int mid=(ln+rn)>>1;
build(lc,ln,mid,x);
build(rc,mid+1,rn,x);
pushup(tr[p],tr[lc],tr[rc]);
}
void update(int p,int ln,int rn,int op)
{
if(ln<=tr[p].l&&tr[p].r<=rn)
{
pd(p,op);
return;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(ln<=mid)update(lc,ln,rn,op);
if(rn>=mid+1)update(rc,ln,rn,op);
pushup(tr[p],tr[lc],tr[rc]);
}
node query(int p,int ln,int rn)
{
if(ln<=tr[p].l&&tr[p].r<=rn)return tr[p];
int mid=(tr[p].l+tr[p].r)>>1;
pushdown(p);
if(rn<=mid)return query(lc,ln,rn);
if(ln>=mid+1)return query(rc,ln,rn);
node tmp;
pushup(tmp,query(lc,ln,rn),query(rc,ln,rn));
return tmp;
}
bool check(int x)
{
build(1,1,n,x);
// for(int i=1;i<=n;i++)cout<<query(1,i,i).sum1<<' ';
// cout<<endl;
for(int i=1;i<=m;i++)
{
node res=query(1,ql[i],qr[i]);
int sum1=res.sum1,sum0=res.sum0;
if(qop[i]==0)
{
if(ql[i]<=ql[i]+sum0-1)update(1,ql[i],ql[i]+sum0-1,0);
if(ql[i]+sum0<=qr[i])update(1,ql[i]+sum0,qr[i],1);
}
else
{
if(ql[i]<=ql[i]+sum1-1)update(1,ql[i],ql[i]+sum1-1,1);
if(ql[i]+sum1<=qr[i])update(1,ql[i]+sum1,qr[i],0);
}
// for(int i=1;i<=n;i++)cout<<query(1,i,i).sum1<<' ';
// cout<<endl;
}
return (query(1,q,q).sum1==1);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>qop[i]>>ql[i]>>qr[i];
cin>>q;
int l=1,r=n,mid;
while(l<r)
{
mid=(l+r+1)>>1;
if(check(mid))l=mid;
else r=mid-1;
// cout<<"l="<<l<<" ; r="<<r<<" ; mid="<<mid<<endl;
// for(int i=1;i<=n;i++)cout<<query(1,i,i).sum1<<' ';
// cout<<endl<<endl;
}
cout<<l;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战