JZOJ 5947. 【NOIP2018模擬11.02】初音未來
阿新 • • 發佈:2018-12-19
題目
Hercier作為一位喜愛Hatsune Miku的OIer,痛下決心,將Vocaloid買回了家。開啟之後,你發現介面是一個長為n的序列,代表音調,並形成了全排列。你看不懂日語,經過多次嘗試,你只會用一個按鈕:將一段區間按升序排序。不理解音樂的Hercier決定寫一個指令碼,進行m次操作,每次對一段區間進行操作。可惜Hercier不會寫指令碼,他找到了在機房裡的你,請你模擬出最後的結果。
資料範圍
題解
70分做法: 40分送的。 測試點3-7,直接就二分答案就好了。變成只有0和1組成的序列。 桶排,同樣能拿到70分。 100分: 抓住重點:考慮氣泡排序與逆序對的關係。如果一段序列沒有逆序對,那麼可以不理之。 一種水法,暴力桶排,修改b[i]的字首和s[i]。 b[i]表示a[i]和a[i-1]是否構成逆序對(0/1) 如果s[r]=s[l],那麼操作[l,r]無用。 迴圈展開一下即可。 正解: 逆序對不超過個。 如果一段序列沒有逆序對,那麼可以不理之。 維護一個線段樹,對勢能分析整體感知,看似暴力的方法,實際上是能過的。 線段樹維護b[i] 如果每次找到最左邊的逆序對所在的位置x,經過一些修改,使得[l,x]這段區間變得有序,那麼不是做完了嗎? 反正最多隻會被交換次。
程式碼
#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 namespace std;
bool tr[N<<2];
bool la[N<<2];
int i,j,k,l,r,n,m,ans;
int L,R,opl,opr,opx,opz;
int vl,vr,Mid;
int a[N],b[N];
int read(){
int fh=0,rs=0;char ch=0;
while((ch<'0'||ch>'9')&& (ch^'-'))ch=getchar();
if(ch=='-')fh=1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return fh?-rs:rs;
}
void Swap(int &x,int &y){
x=x^y;
y=x^y;
x=x^y;
}
void downld(int ps){
if(la[ps]){
tr[ps<<1]=tr[(ps<<1)|1]=0;
la[ps<<1]=la[(ps<<1)|1]=1;
la[ps]=0;
}
}
void build(int ps,int l,int r){
if(l==r){
tr[ps]=(a[l]<a[l-1]);
return;
}
int wz=(l+r)>>1;
build(ps<<1,l,wz);
build((ps<<1)|1,wz+1,r);
tr[ps]=tr[ps<<1]|tr[(ps<<1)|1];
}
void change(int ps,int l,int r){
if(l==r){
tr[ps]=1;
return;
}
downld(ps);
int wz=(l+r)>>1;
if(opx<=wz)change(ps<<1,l,wz);
else change((ps<<1)|1,wz+1,r);
tr[ps]=tr[ps<<1]|tr[(ps<<1)|1];
}
void doit(int ps,int l,int r){
if(!tr[ps])return;
if(l==r){
int i,j;
for(j=l;j<=opr&&a[j]<a[j-1];j++)
for(i=j;i>opl&&a[i]<a[i-1];i--)Swap(a[i],a[i-1]);
return;
}
downld(ps);
int wz=(l+r)>>1;
doit(ps<<1,l,wz);
doit((ps<<1)|1,wz+1,r);
}
void query(int ps,int l,int r){
if(!tr[ps])return;
if(opl<=l&&r<=opr){
doit(ps,l,r);
la[ps]=1;tr[ps]=0;
return;
}
downld(ps);
int wz=(l+r)>>1;
if(opl<=wz)query(ps<<1,l,wz);
if(opr>wz)query((ps<<1)|1,wz+1,r);
}
int main(){
n=read();m=read();L=read();R=read();
fo(i,1,n)a[i]=read();
build(1,1,n);
fo(i,1,m){
opl=read(),opr=read();
query(1,1,n);
if(a[opl]<a[opl-1]){
opx=opl;
change(1,1,n);
}
if(a[opr+1]<a[opr]){
opx=opr+1;
change(1,1,n);
}
}
fo(i,L,R)printf("%d ",a[i]);
return 0;
}