并不对劲的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;
}
一些感想

我去年咕了多少。。。

猜你喜欢

转载自www.cnblogs.com/xzyf/p/12933655.html