首页 > 其他分享 >P3165 [CQOI2014] 排序机械臂

P3165 [CQOI2014] 排序机械臂

时间:2024-12-06 12:23:42浏览次数:3  
标签:rs int siz P3165 mi ls 物品 CQOI2014 排序

P3165 [CQOI2014] 排序机械臂

题目描述

为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到高度最低的物品的位置 \(P_1\) ,并把左起第一个物品至 \(P_1\) 间的物品 (即区间 \([1,P_1]\) 间的物品) 反序;第二次找到第二低的物品的位置 \(P_2\) ,并把左起第二个至 \(P_2\) 间的物品 (即区间 \([2,P_2]\) 间的物品) 反序……最终所有的物品都会被排好序。

样例说明

上图给出有六个物品的示例,第一次操作前,高度最低的物品在位置 \(4\) ,于是把第一至第四的物品反序;第二次操作前,第二低的物品在位罝六,于是把第二至六的物品反序……

你的任务便是编写一个程序,确定一个操作序列,即每次操作前第 \(i\) 低的物品所在位置 \(P_i\) ,以便机械臂工作。需要注意的是,如果有高度相同的物品,必须保证排序后它们的相对位置关系与初始时相同。

提示

\(N \le 100000\)

\(P_i \le 10^7\)

Solution:

拿到题目,区间翻转?这不纯文艺平衡树吗?

我们在以编号建一颗平衡树,平衡树节点上挂当前节点的权值以及区间翻转的 \(tag\) 然后我们唯一剩下的问题就是如何在一颗以下标建树的平衡树上查询区间最小值及其编号

我们在每个点上再挂一个值
\(t[x].mi=min{(t[x].val,t[ls],mi,t[rs].mi)}\)

然后查询的时候判断一下 \(t[x].mi\) 落在那个部分就好了

查询最小值:

int find(int x)
{
    int k=1;
    while(1)
    {
        pushdown(x);
        int ls=t[x].ls,rs=t[x].rs;
        if(t[x].mi==t[x].val){k+=t[ls].siz;return k;}
        else
        {
            if(ls&&t[ls].mi==t[x].mi){x=ls;}
            else if(rs&&t[rs].mi==t[x].mi){k+=t[ls].siz+1;x=rs;}
        }

    }
}

Code:

#include<bits/stdc++.h>
const int N=1e5+5;
const int inf=1e7;
using namespace std;
int n,m,cnt,rt;
// FHQ - Treap
struct Tree{
    int ls,rs,tag,val,siz,pri,mi;
}t[N];
int rd(){return rand()*rand()+rand()*17;}
int new_Node(int x)
{
    t[++cnt]=Tree{0,0,0,x,1,rd(),x};
    return cnt;
}
void pushup(int x)
{
    int ls=t[x].ls,rs=t[x].rs;
    t[x].siz=t[ls].siz+t[rs].siz+1;
    t[x].mi=t[x].val;
    if(ls)t[x].mi=min(t[x].mi,t[ls].mi);
    if(rs)t[x].mi=min(t[x].mi,t[rs].mi);
}
void pushdown(int x)
{
    if(!t[x].tag)return;
    swap(t[x].ls,t[x].rs);
    t[t[x].ls].tag^=1;
    t[t[x].rs].tag^=1;
    t[x].tag=0;
}
void splite(int x,int k,int &a,int &b)
{
    if(!x){a=b=0;return ;}
    pushdown(x);
    int tmp=t[t[x].ls].siz+1;
    if(k>=tmp){a=x;splite(t[x].rs,k-tmp,t[x].rs,b);}
    else {b=x;splite(t[x].ls,k,a,t[x].ls);}
    pushup(x);
}
int merge(int x,int y)
{
    if(!x||!y){return x+y;}
    if(t[x].pri<t[y].pri)
    {
        pushdown(x);
        t[x].rs=merge(t[x].rs,y);
        pushup(x);
        return x;
    }
    else
    {
        pushdown(y);
        t[y].ls=merge(x,t[y].ls);
        pushup(y);
        return y;
    }
}
int find(int x)
{
    int k=1;
    while(1)
    {
        pushdown(x);
        int ls=t[x].ls,rs=t[x].rs;
        if(t[x].mi==t[x].val){k+=t[ls].siz;return k;}
        else
        {
            if(ls&&t[ls].mi==t[x].mi){x=ls;}
            else if(rs&&t[rs].mi==t[x].mi){k+=t[ls].siz+1;x=rs;}
        }

    }
}
struct Node{
    int val,id;
    bool operator <(const Node &n)const{

        return val==n.val ? id<n.id : val<n.val;
    }
}q[N];
int a[N];
void work()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    scanf("%d",&q[i].val),q[i].id=i;
    sort(q+1,q+1+n);
    for(int i=1;i<=n;i++)a[q[i].id]=i;
    for(int i=1;i<=n;i++)rt=merge(rt,new_Node(a[i]));
    for(int i=1;i<=n;i++)
    {
        int k=find(rt),x,y,z;
        splite(rt,k-1,x,y);//x:[1,k-1] y:[k,n]
        splite(y,1,y,z);
        t[x].tag^=1;
        rt=merge(x,z);
        printf("%d ",k+i-1);
    }

}
int main()
{
    srand(7758258);
    //freopen("P3165.in","r",stdin);freopen("P3165.out","w",stdout);
    work();
    return 0;
}

标签:rs,int,siz,P3165,mi,ls,物品,CQOI2014,排序
From: https://www.cnblogs.com/LG017/p/18590498

相关文章

  • 二叉排序树的定义以及相关操作
    二叉排序树:又称二叉查找树(BST,BinarySearchTree)二叉排序树的性质:左子树节点值<根节点值<右子树节点值所以 对一棵二叉排序树进行中序遍历,会得到一个递增的序列定义二叉排序树的结点//二叉排序树的结点typedefstructBSTNode{intkey;structBSTNode*lc......
  • C++14关联容器set自定义排序函数报错
    十年前的一个C++项目编译报错:“boolcompatetor_asc::operator()(conststd::wstring&,conststd::wstring&)”:不能将“this”指针从“constcompatetor_asc”转换为“compatetor_asc&”。对应的代码如下:classcompatetor_asc{public:booloperator()(conststd::......
  • vue基础之11:列表排序
    欢迎来到“雪碧聊技术”CSDN博客!在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目......
  • SQL-基础语法 - 排序
    在查询数据时,我们有时希望对结果按照某个字段的值进行排序,以便更好地查看数据。在SQL中,我们可以使用ORDERBY关键字来实现排序操作。ORDERBY后面跟上需要排序的字段,可以选择升序(ASC)或降序(DESC)排列。示例假设有一张名为students的数据表,它存储了学生信息,包括学生姓名(nam......
  • #C01L06P01. C01.L06.复合语句、数值交换、三个数的最值与排序.复合语句
    例1:运行下列程序,输入5,观察运行结果并思考程序是怎样运行的。#include<bits/stdc++.h>usingnamespacestd;intmain(){ intn,a=0,b=0,c=0; cin>>n; if(n<0) a=a+2; b=b+2; c=c+2; cout<<a<<""<<b<<""<<c; re......
  • Day6:杨辉三角、冒泡选择排序、交集存新数组、十名学生成绩、四组学生成绩
    题目:使用二维数组输出杨辉三角分析代码#include<stdio.h>#include<string.h>#include<stdlib.h>intmain(intargc,constchar*argv[]){      inth=10,l=10;   intarr[h][l];   //初始化数组   for(inti=0;i<h;i++)   {  ......
  • 常见排序整合(python版)
    1.冒泡排序#bubblesort#时间复杂度为o(n^2)#升序和降序只需要改动其中的一个箭头方向即可defbubble_sort(li):count=1foriinrange(len(li)-2):exchange=Falseforjinrange(len(li)-i-1):ifli[j]>li[j+1]:......
  • Acwing1696. 困牛排序
    题意给定一个n个数的排列,每次操作将第一个数插入到任意数之后,求多少次操作后排列为升序若\(a_i>a_{i+1}\)那么至少操作i次才能将a_i插入到\(a_{i+1}\)之后这时我们思考是否可以通过i次操作,使得序列有序,假如此时\(a_{i+1~n}\)有序于是我们可以通过插入排序,使得序列有序如何......
  • Java中集合的的多字段排序(链式排序)详解
    链式排序(ChainedSorting)详解链式排序(ChainedSorting)是指通过多个比较条件,依次对数据进行排序的方法。它是一种在一个排序规则的基础上,利用第二排序规则、第三排序规则等,来细化排序过程的技术。在Java中,Comparator接口提供了非常便捷的方式来实现链式排序,通常应用于复......
  • 蓝桥杯c++算法秒杀【7】之数据结构(修改数组、翻转括号序列、双向排序:::非常典型的必刷例
    别忘了请点个赞+收藏+关注支持一下博主喵!!!! ! !  关注博主,更多蓝桥杯nice题目静待更新:)  数据结构一、修改数组【问题描述】        给定一个长度为N的数组A=[A1,A2,...,AN],数组中有可能有重复出现的整数。        现在小明要按以下方法将其......