BZOJ 4552 排序

省选TM都能有BC原题?

。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100500
#define inf 1000000007
using namespace std;
int n,m,a[maxn],l=inf,r=0,mi,q;
int ls[maxn<<2],rs[maxn<<2],lazy[maxn<<2],sum[maxn<<2],root,tot=0;
int pos[maxn],ans;
struct move
{
    int type,l,r;
}p[maxn];
void build(int &now,int left,int right)
{
    now=++tot;lazy[now]=-1;
    if (left==right)
    {
        pos[left]=now;
        if (a[left]>=mi) {lazy[now]=1;sum[now]=1;}
        else {lazy[now]=0;sum[now]=0;}
        return;
    }
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    sum[now]=sum[ls[now]]+sum[rs[now]];
}
void pushdown(int now,int left,int right)
{
    if (lazy[now]==-1) return;
    if (left==right) return;
    int mid=(left+right)>>1;
    if (lazy[now]==0)
    {
        lazy[ls[now]]=0;sum[ls[now]]=0;
        lazy[rs[now]]=0;sum[rs[now]]=0;
    }
    else
    {
        lazy[ls[now]]=1;sum[ls[now]]=mid-left+1;
        lazy[rs[now]]=1;sum[rs[now]]=right-mid;
    }
    lazy[now]=-1;
}
int query(int now,int left,int right,int l,int r)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
        return sum[now];
    int mid=(left+right)>>1;
    if (r<=mid) return query(ls[now],left,mid,l,r);
    else if (l>=mid+1) return query(rs[now],mid+1,right,l,r);
    else return query(ls[now],left,mid,l,mid)+query(rs[now],mid+1,right,mid+1,r);
}
void modify(int now,int left,int right,int l,int r,int p)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        lazy[now]=p;
        if (p==0) sum[now]=0;
        else sum[now]=right-left+1;
        return;
    }
    int mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,p);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,p);
    else
    {
        modify(ls[now],left,mid,l,mid,p);
        modify(rs[now],mid+1,right,mid+1,r,p);
    }
    sum[now]=sum[ls[now]]+sum[rs[now]];
}
void work0(int x)
{
    int len=p[x].r-p[x].l+1,lenr=query(root,1,n,p[x].l,p[x].r);
    if (p[x].l<=p[x].l+(len-lenr)-1) modify(root,1,n,p[x].l,p[x].l+(len-lenr)-1,0);
    if (p[x].l+(len-lenr)<=p[x].r) modify(root,1,n,p[x].l+(len-lenr),p[x].r,1);
}
void work1(int x)
{
    int len=p[x].r-p[x].l+1,lenl=query(root,1,n,p[x].l,p[x].r);
    if (p[x].l<=p[x].l+lenl-1) modify(root,1,n,p[x].l,p[x].l+lenl-1,1);
    if (p[x].l+lenl<=p[x].r) modify(root,1,n,p[x].l+lenl,p[x].r,0);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        l=min(l,a[i]);
        r=max(r,a[i]);
    }
    for (int i=1;i<=m;i++)
        scanf("%d%d%d",&p[i].type,&p[i].l,&p[i].r);
    scanf("%d",&q);
    while (l<=r)
    {
        tot=0;
        mi=(l+r)>>1;
        build(root,1,n);
        for (int i=1;i<=m;i++)
        {
            if (p[i].type==0) work0(i);
            else work1(i);
        }
        int regis=query(root,1,n,q,q);
        if (regis==1) {ans=mi;l=mi+1;}
        else r=mi-1;
    }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-10-25 21:10:12

BZOJ 4552 排序的相关文章

[BZOJ] 4552: [Tjoi2016&amp;Heoi2016]排序 #二分+线段树+算法设计策略

4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1451  Solved: 734[Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,r

bzoj 4552 [Tjoi2016&amp;Heoi2016]排序——二分答案

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成区间赋值了. #include<cstdio> #include<cstring> #include<algorithm> #define ls Ls[cr] #define rs Rs[cr] using namespace std; const int N=1e5+5,

排序(bzoj 4552)

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

bzoj 4552: [Tjoi2016&amp;Heoi2016]排序

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

[BZOJ 1552] 排序机械臂

Splay大法是坠吼滴! 1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 436  Solved: 186[Submit][Status][Discuss] Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. Output 输出共一行,N个用空格隔开的正整数P1,P2,P3

bzoj 4552

二分 + 线段树二分一个值 x, 讲原序列转化为01序列1表示该数>x, 0表示改数<x;线段树维护区间和进行判断 #include <bits/stdc++.h> const int N = 1e5 + 10; #define gc getchar() int n, m, Q; int A[N], B[N]; int S[N << 2], W[N << 2], F[N << 2]; int opt[N], lask[N], rask[N]; i

【刷题记录】杂题记录

1.[bzoj 4552][Tjoi2016&Heoi2016]排序 题意:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序.排序分为两种:(0,l,r)表示将区间[l,r]的数字升序排序:(1,l,r)表示将区间[l,r]的数字降序排序.最后询问第q位置上的数字. 分析:二分答案,将所有值小于等于当前值的数赋为0,其余赋为1.利用线段树可以通过统计区间内数字1的个数来使当前区间有序.进行m次局部排序后可以得到答案与当前值的大小关系,满足可二分性. 1 #include<cstd

4552: [Tjoi2016&amp;Heoi2016]排序

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

BZOJ 2080: [Poi2010]Railway 双栈排序

2080: [Poi2010]Railway Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 140  Solved: 35[Submit][Status][Discuss] Description 一个铁路包含两个侧线1和2,右边由A进入,左边由B出去(看下面的图片) 有n个车厢在通道A上,编号为1到n,它们被安排按照要求的顺序(a1,a2,a3,a4....an)进入侧线,进去还要出来,它们要按照编号顺序(1,2,3,4,5....n)从通道B