并不对劲的bzoj4552:p2824:[HEOI2016/TJOI2016]排序
题目大意
有\(n\)个数\(a_1,...,a_n\),\(m\)次操作。
操作有两种:
1.给出\(l,r\),将\(a_l,...,a_r\)升序排序;
2.给出\(l,r\),将\(a_l,...,a_r\)降序排序。
所有操作结束后,给出\(q\),问\(a_q\)。
\(n,m\leq 10^5\)。
题解
给一个01序列排序时,肯定会把所有0放在前面,把所有1放在后面,所有可以统计1的个数,再进行两次区间赋值,排一次序时间\(\Theta(log\space n)\)。
总共只有一次询问,可以二分\(a_q\)的值,每次把大于等于二分的那个值的当成1,小于那个值的当成0。
总时间复杂度\(\Theta(n\times log ^2\space n)\)。
代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define re register
#define maxn 100010
#define ls (nd<<1)
#define rs (nd<<1|1)
#define mi (l+r>>1)
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(isdigit(ch)==0 && ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
int f=0;char ch[20];
if(!x){puts("0");return;}
if(x<0){putchar('-');x=-x;}
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
int n,m,a[maxn],tmp[maxn],tr[maxn<<2],mk[maxn<<2],ql[maxn],qr[maxn],qf[maxn],q,ans=-1,ox,oy,oz;
inline void mark(re int nd,re int l,re int r,re int k){tr[nd]=k*(r-l+1),mk[nd]=k;}
inline void pd(re int nd,re int l,re int r){if(mk[nd]!=-1&&l<r)mark(ls,l,mi,mk[nd]),mark(rs,mi+1,r,mk[nd]),mk[nd]=-1;}
inline void pu(re int nd){tr[nd]=tr[ls]+tr[rs];}
inline void build(re int nd,re int l,re int r)
{
if(l==r){tr[nd]=tmp[l];return;}
build(ls,l,mi),build(rs,mi+1,r),pu(nd);
}
inline int ask(re int nd,re int l,re int r,re int x,re int y)
{
pd(nd,l,r);
if(x<=l&&r<=y){return tr[nd];}
if(y<l||r<x)return 0;
int lans=ask(ls,l,mi,x,y),rans=ask(rs,mi+1,r,x,y);
return lans+rans;
}
inline void add(re int nd,re int l,re int r,re int x,re int y,re int k)
{
pd(nd,l,r);
if(x<=l&&r<=y){mark(nd,l,r,k);return ;}
if(y<l||r<x)return;
add(ls,l,mi,x,y,k),add(rs,mi+1,r,x,y,k),pu(nd);
}
inline int check(re int x)
{
rep(i,1,n)tmp[i]=(a[i]>=x)?1:0;
memset(tr,0,sizeof(tr));
memset(mk,-1,sizeof(mk));
build(1,1,n);
rep(i,1,m)
{
int num=ask(1,1,n,ql[i],qr[i]);
ox=ql[i],oy=(qf[i])?ql[i]+num-1:qr[i]-num,oz=qr[i];
if(qf[i])add(1,1,n,ox,oy,1),add(1,1,n,oy+1,oz,0);
else add(1,1,n,ox,oy,0),add(1,1,n,oy+1,oz,1);
}
return ask(1,1,n,q,q);
}
int main()
{
n=read(),m=read();
rep(i,1,n)a[i]=read();
rep(i,1,m)qf[i]=read(),ql[i]=read(),qr[i]=read();
q=read();
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))ans=max(ans,mid),l=mid+1;
else r=mid-1;
}
write(ans);
return 0;
}
一些感想
我去年咕了多少。。。