【bzoj4552】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】排序

来源:互联网 发布:linux 关闭ntpdate 编辑:程序博客网 时间:2024/05/17 14:15

题目

在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字。

分析

二分答案,
把二分出的ans与原序列比较,小于ans的数改为-1,大于ans的数改为1。
对于输入的每一个修改,用线段树来处理。
最后求出q位上的数是-1还是1,然后接着二分。

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>const int maxlongint=2147483647;const int mo=1000000007;const int N=100005;using namespace std;int a[N],n,m,re[N][4],k,ans,lazy[N*5],_0[N*5],_1[N*5];int down(int v,int mid,int l,int r){    if(lazy[v]==-1)    {        lazy[v*2+1]=lazy[v*2]=lazy[v];        _0[v*2]=mid-l+1;        _0[v*2+1]=r-(mid+1)+1;        _1[v*2]=0;        _1[v*2+1]=0;    }    if(lazy[v]==1)    {        lazy[v*2+1]=lazy[v*2]=lazy[v];        _1[v*2]=mid-l+1;        _1[v*2+1]=r-(mid+1)+1;        _0[v*2]=0;        _0[v*2+1]=0;    }    lazy[v]=0;}int put(int v,int l,int r,int x,int y){    if(l==r)    {        if(y==-1)            _0[v]=1;                else _1[v]=1;        return 0;    }    int mid=(l+r)/2;    if(x<=mid)        put(v*2,l,mid,x,y);    else        put(v*2+1,mid+1,r,x,y);    _0[v]=_0[v*2]+_0[v*2+1];    _1[v]=_1[v*2]+_1[v*2+1];}int get(int v,int l,int r,int x,int y){    if(l==x && r==y)    {        return _1[v];    }    int mid=(l+r)/2;    down(v,mid,l,r);    int o;    if(y<=mid)        o=get(v*2,l,mid,x,y);    else    if(x>mid)        o=get(v*2+1,mid+1,r,x,y);    else        o=get(v*2,l,mid,x,mid)+get(v*2+1,mid+1,r,mid+1,y);    _0[v]=_0[v*2]+_0[v*2+1];    _1[v]=_1[v*2]+_1[v*2+1];    return o;}int change(int v,int l,int r,int x,int y,int value){    if(y<x) return 0;    int mid=(l+r)/2;    if(l==x && r==y)    {        lazy[v]=value;        if(value<0)        {            _0[v]=r-l+1;            _1[v]=0;        }        else        {            _1[v]=r-l+1;            _0[v]=0;            }        return 0;    }    down(v,mid,l,r);    if(y<=mid)        change(v*2,l,mid,x,y,value);    else    if(x>mid)        change(v*2+1,mid+1,r,x,y,value);    else        change(v*2,l,mid,x,mid,value),change(v*2+1,mid+1,r,mid+1,y,value);    _0[v]=_0[v*2]+_0[v*2+1];    _1[v]=_1[v*2]+_1[v*2+1];}int find(int v,int l,int r,int x){    if(l==r)    {        return _0[v];    }    int mid=(l+r)/2;    down(v,mid,l,r);    int o;    if(x<=mid)        o=find(v*2,l,mid,x);    else        o=find(v*2+1,mid+1,r,x);    _0[v]=_0[v*2]+_0[v*2+1];    _1[v]=_1[v*2]+_1[v*2+1];    return o;}bool check(int x){    memset(lazy,0,sizeof(lazy));    memset(_0,0,sizeof(_0));    memset(_1,0,sizeof(_1));    for(int i=1;i<=n;i++)    {        int g=a[i]<=x?-1:1;        put(1,1,n,i,g);    }    for(int i=1;i<=m;i++)    {        int p1=get(1,1,n,re[i][2],re[i][3]);        if(!re[i][1])        {            change(1,1,n,re[i][2],re[i][3]-p1,-1);            change(1,1,n,re[i][3]-p1+1,re[i][3],1);        }        else        {            change(1,1,n,re[i][2],re[i][2]+p1-1,1);            change(1,1,n,re[i][2]+p1,re[i][3],-1);          }    }    if(find(1,1,n,k))        return true;            else return false;}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",&re[i][1],&re[i][2],&re[i][3]);    }    scanf("%d",&k);    int l=1,r=n;    while(l<r)    {        int mid=(l+r)/2;        if(check(mid))        {            r=mid;        }        else        {            l=mid+1;        }    }    printf("%d",l);}
1 0
原创粉丝点击