题目
Hercier作为一位喜爱Hatsune Miku的OIer,痛下决心,将Vocaloid买回了家。打开之后,你发现界面是一个长为n的序列,代表音调,并形成了全排列。你看不懂日语,经过多次尝试,你只会用一个按钮:将一段区间按升序排序。不理解音乐的Hercier决定写一个脚本,进行m次操作,每次对一段区间进行操作。可惜Hercier不会写脚本,他找到了在机房里的你,请你模拟出最后的结果。
数据范围
题解
70分做法:
O ( m l o g 2 n ) O(m\ log^2n) O(m log2n)
40分送的。
测试点3-7,直接就二分答案就好了。变成只有0和1组成的序列。
O ( n m ) O(nm) O(nm)桶排,同样能拿到70分。
100分:
抓住重点:考虑冒泡排序与逆序对的关系。如果一段序列没有逆序对,那么可以不理之。
一种水法,暴力桶排,修改b[i]的前缀和s[i]。
b[i]表示a[i]和a[i-1]是否构成逆序对(0/1)
如果s[r]=s[l],那么操作[l,r]无用。
循环展开一下即可。
正解:
逆序对不超过 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1)个。
如果一段序列没有逆序对,那么可以不理之。
维护一个线段树,对势能分析整体感知,看似暴力的方法,实际上是能过的。
线段树维护b[i]
如果每次找到最左边的逆序对所在的位置x,经过一些修改,使得[l,x]这段区间变得有序,那么不是做完了吗?
反正最多只会被交换 O ( n 2 ) O(n^2) O(n2)次。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 1510
#define Min(x,y) ((x)<(y)?(x):(y))
#define fo(i,a,b) for(i=a;i<=b;i++)
using names