C38 线段树+二分 P2824 [HEOI2016/TJOI2016] 排序
视频链接:224 线段树+二分 [HEOI2016TJOI2016] 排序_哔哩哔哩_bilibili
Luogu P2824 [HEOI2016/TJOI2016] 排序
// 线段树+二分 nlognlogn #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=100010; #define ls u<<1 #define rs u<<1|1 int n,m,q; int a[N],op[N],L[N],R[N]; struct tree{ //线段树 int l,r; int sum,tag; }tr[N<<2]; //sum:区间1的个数 //tag:-1:区间无标记,0/1:区间赋值为0/1 void pushup(int u){ //上传 tr[u].sum=tr[ls].sum+tr[rs].sum; } void pushdown(int u){ //下传 if(tr[u].tag==-1) return; tr[ls].sum=tr[u].tag*(tr[ls].r-tr[ls].l+1); tr[rs].sum=tr[u].tag*(tr[rs].r-tr[rs].l+1); tr[ls].tag=tr[rs].tag=tr[u].tag; tr[u].tag=-1; //清空懒标记 } void build(int u,int l,int r,int x){ //建树 tr[u]={l,r,a[l]>=x,-1}; if(l==r) return; int m=l+r>>1; build(ls,l,m,x); build(rs,m+1,r,x); pushup(u); } void change(int u,int x,int y,int k){ //区修 if(x>tr[u].r || y<tr[u].l) return; if(x<=tr[u].l && tr[u].r<=y){ tr[u].sum=k*(tr[u].r-tr[u].l+1); tr[u].tag=k; return; } pushdown(u); change(ls,x,y,k); change(rs,x,y,k); pushup(u); } int query(int u,int x,int y){ //区查 if(x>tr[u].r || y<tr[u].l) return 0; if(x<=tr[u].l&&tr[u].r<=y) return tr[u].sum; pushdown(u); return query(ls,x,y)+query(rs,x,y); } bool check(int x){ build(1,1,n,x); for(int i=1; i<=m; i++){ int l=L[i],r=R[i]; int cnt=query(1,l,r); //1的个数 if(op[i]==0){ change(1,r-cnt+1,r,1); change(1,l,r-cnt,0); } else{ change(1,l,l+cnt-1,1); change(1,l+cnt,r,0); } } return query(1,q,q); //q位置的数 } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++)scanf("%d",&a[i]); for(int i=1; i<=m; i++) scanf("%d%d%d",&op[i],&L[i],&R[i]); scanf("%d",&q); int l=0,r=n+1; //二分答案 while(l+1<r){ int mid=l+r>>1; check(mid)?l=mid:r=mid; } printf("%d\n",l); return 0; }
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N=100010; #define ls u<<1 #define rs u<<1|1 #define mid (l+r)/2 int n,m,q; int a[N],op[N],L[N],R[N]; int sum[4*N],tag[4*N]; void pushup(int u){ sum[u]=sum[ls]+sum[rs]; } void pushdown(int u,int l,int r){ if(tag[u]==-1) return; sum[ls]=tag[u]*(mid-l+1); sum[rs]=tag[u]*(r-mid); tag[ls]=tag[rs]=tag[u]; tag[u]=-1; } void build(int u,int l,int r,int x){ sum[u]=a[l]>=x; tag[u]=-1; if(l==r) return; build(ls,l,mid,x); build(rs,mid+1,r,x); pushup(u); } void change(int u,int l,int r,int x,int y,int k){ if(x>r || y<l) return; if(x<=l && r<=y){ sum[u]=k*(r-l+1); tag[u]=k; return; } pushdown(u,l,r); change(ls,l,mid,x,y,k); change(rs,mid+1,r,x,y,k); pushup(u); } int query(int u,int l,int r,int x,int y){ if(x>r || y<l) return 0; if(x<=l && r<=y) return sum[u]; pushdown(u,l,r); return query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y); } bool check(int x){ build(1,1,n,x); for(int i=1; i<=m; i++){ int l=L[i],r=R[i]; int cnt=query(1,1,n,l,r); if(op[i]==0){ change(1,1,n,l,r-cnt,0); change(1,1,n,r-cnt+1,r,1); } else{ change(1,1,n,l+cnt,r,0); change(1,1,n,l,l+cnt-1,1); } } return query(1,1,n,q,q); } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++)scanf("%d",&a[i]); for(int i=1; i<=m; i++) scanf("%d%d%d",&op[i],&L[i],&R[i]); scanf("%d",&q); int l=0,r=n+1; while(l+1<r){ check(mid)?l=mid:r=mid; } printf("%d\n",l); return 0; }