【JZOJ5947】【NOIP2018模拟11.02】初音未来(miku)(逆序对排序+线段树)

2023-10-22 09:30

本文主要是介绍【JZOJ5947】【NOIP2018模拟11.02】初音未来(miku)(逆序对排序+线段树),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

  • Hercier作为一位喜爱Hatsune Miku的OIer,痛下决心,将Vocaloid买回了家。打开之后,你发现界面是一个长为n的序列,代表音调,并形成了全排列。你看不懂日语,经过多次尝试,你只会用一个按钮:将一段区间按升序排序。不理解音乐的Hercier决定写一个脚本,进行m次操作,每次对一段区间进行操作。可惜Hercier不会写脚本,他找到了在机房里的你,请你模拟出最后的结果。

Input

在这里插入图片描述

Output

在这里插入图片描述

Data Constraint

在这里插入图片描述

Solution

  • 我们知道冒泡排序的交换次数是逆序对个数;而冒泡排序的交换方法是交换相邻逆序对。
  • 既然这样,可以将本题的排序变为逆序对排序。我们记录下所有的相邻逆序对,用一棵线段树存储一段区间中最左边的相邻逆序对。对于询问 ( l i , r i ) (l_i,r_i) (li,ri),我们不断地寻找区间 [ l i , r i ] [l_i,r_i] [li,ri]中最靠左的相邻逆序对,若找得到,则交换之,同时维护线段树。
  • 分析一波时间复杂度。我们至多进行 n 2 n^2 n2次交换,每次交换前需要 log ⁡ 2 n \log_2n log2n的查询时间,交换后需要 log ⁡ 2 n \log_2n log2n的维护时间。因此,总时间复杂度为 O ( ( n 2 + m ) log ⁡ 2 n ) O((n^2+m)\log_2n) O((n2+m)log2n)

Code

#include <bits/stdc++.h>
#define A v<<1
#define B A|1
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;const int N=1501;
int i,n,m,L,R,a[N],px,pv,t[N*N],x,y,pos;inline int min(int x,int y) {return x<y?x:y;}void read(int&x)
{char ch=getchar(); x=0;for(;!isdigit(ch);ch=getchar());for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
}void modify(int v,int l,int r)
{if(l==r) {t[v]=pv; return;}int mid=l+r>>1;px<=mid ? modify(A,l,mid) : modify(B,mid+1,r);t[v]=min(t[A],t[B]);
}
void ins(int i)
{px=i; pv=(a[i]>a[i+1]?i:n+1);modify(1,1,n);
}int query(int v,int l,int r)
{if(x<=l&&r<=y) return t[v];if(y< l||r< x) return n+1;int mid=l+r>>1;return min(query(A,l,mid),query(B,mid+1,r));
}int main()
{freopen("miku.in","r",stdin);freopen("miku.out","w",stdout);read(n); read(m); read(L); read(R);memset(t,127,sizeof t);fo(i,1,n) {read(a[i]);if(i>1) ins(i-1);}fo(i,1,m){read(x); read(y);rep:pos=query(1,1,n);if(pos>=y) continue;swap(a[pos],a[pos+1]);if(pos>1) ins(pos-1);ins(pos); ins(pos+1);goto rep;}fo(i,L,R) printf("%d ",a[i]);
}

这篇关于【JZOJ5947】【NOIP2018模拟11.02】初音未来(miku)(逆序对排序+线段树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/260565

相关文章

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while