1. 程式人生 > >【JZOJ A組】初音未來

【JZOJ A組】初音未來

Description

Hercier作為一位喜愛Hatsune Miku的OIer,痛下決心,將Vocaloid買回了家。開啟之後,你發現介面是一個長為n的序列,代表音調,並形成了全排列。你看不懂日語,經過多次嘗試,你只會用一個按鈕:將一段區間按升序排序。不理解音樂的Hercier決定寫一個指令碼,進行m次操作,每次對一段區間進行操作。可惜Hercier不會寫指令碼,他找到了在機房裡的你,請你模擬出最後的結果。

Input

在這裡插入圖片描述

Output

在這裡插入圖片描述

Sample Input

5 2 1 5
5 1 4 2 3
1 3
2 4

樣例2
見下發檔案

Sample Output

1 2 4 5 3

樣例解釋:
在這裡插入圖片描述

Data Constraint

在這裡插入圖片描述

思路

一個序列的逆序對最多總共有O(n2)個,每次交換一個逆序對個數一定會減少一個。

所以我們可以考慮不停地交換相鄰的逆序對,每次交換看一下相鄰的是否會在相鄰的位置產生逆序對,然後加入佇列

逆序對的位置隨便拿一個數據結構即可

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
set<int> s;
int n,m,L,R,a[1577];
int main()
{
	freopen("miku.in","r",stdin); freopen("miku.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&L,&R);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1; i<=n-1; i++)
	{
		if(a[i]>a[i+1]) s.insert(i);
	}
	while(m--)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		set<int>::iterator t=s.lower_bound(l);
		while(*t<r)
		{
			int p=*t;
			swap(a[p],a[p+1]); s.erase(p);
			if(a[p-1]>a[p]) s.insert(p-1);
			if(a[p+1]>a[p+2]) s.insert(p+1);
			t=s.lower_bound(l);
		}
	}
	for(int i=L; i<=R; i++) printf("%d ",a[i]);
}