[loj2736][JOISC 2016 Day3]回轉壽司——分塊+堆 dalaos' blogs Some Links
阿新 • • 發佈:2018-11-03
題目大意:
給出一個有
個點的環,環上各點有一個初始權值
。
給出
個詢問,每次詢問給出一個區間
和一個值
,對於
的變動定義如下(
可能會小於
因為是環形):
for (int i = l; i <= r; i++) if(a[i] > A) swap(a[i],A);
對於每個詢問,回答遍歷完區間
後
的最終值。
注:我們按逆時針方向在環上編號,並規定
為從位置編號為
的點逆時針遍歷至位置編號為
的點所經過點的集合。
思路:
這種看起來怎麼都不好做的題目考慮分塊。
對於這個操作,我們對於每一塊顯然只需要取出其中最大的元素即可,用一個堆來維護每一個塊的中的元素。
但是對於邊角塊,修改的時候可以暴力修改,可我們也需要知道每一個元素的具體位置,於是這裡有了一種重構的操作:
我們將每一次放入這個塊內的元素記錄下來,按照從小到大的順序進行那種交換的操作,只考慮最終的結果,不難發現這樣是正確的,用一個小根堆維護即可。
時間複雜度
。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<endl
typedef long long ll;
using namespace std;
void File(){
freopen("in.in","r",stdin);
freopen("in.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=4e5+10;
const int maxb=800+10;
const int B=600;
int n,q,a[maxn],bel[maxn],L[maxb],R[maxb];
priority_queue<int>big[maxb];
priority_queue<int,vector<int>,greater<int> >small[maxb];
void rebuild(int id){
if(small[id].empty())return;
REP(i,L[id],R[id]){
if(a[i]>small[id].top()){
int t=small[id].top();
small[id].pop();
small[id].push(a[i]);
a[i]=t;
}
}
while(!small[id].empty())small[id].pop();
}
int modify_block(int l,int r,int x){
int id=bel[l];
REP(i,l,r)if(a[i]>x)swap(x,a[i]);
while(!big[id].empty())big[id].pop();
REP(i,L[id],R[id])big[id].push(a[i]);
//REP(i,L[id],R[id])cout<<a[i]<<" ";
//cout<<endl;
return x;
}
int modify(int l,int r,int x){
//debug(l); debug(r);
int bl=bel[l],br=bel[r],t;
rebuild(bel[l]); rebuild(bel[r]);
if(bl==br)return modify_block(l,r,x);
else{
x=modify_block(l,R[bl],x);
REP(i,bl+1,br-1)if(big[i].top()>x){
t=big[i].top(); big[i].pop();
big[i].push(x); small[i].push(x);
x=t;
}
return modify_block(L[br],r,x);
}
}
void init(){
read(n); read(q);
REP(i,1,n)read(a[i]);
memset(L,63,sizeof(L));
memset(R,-1,sizeof(R));
REP(i,1,n){
bel[i]=(i-1)/B+1;
L[bel[i]]=min(L[bel[i]],i);
R[bel[i]]=max(R[bel[i]],i);
}
REP(i,1,n)big[bel[i]].push(a[i]);
}
void work(){
int l,r,x;
REP(i,1,q){
read(l),read(r),read(x);
if(l<=r)printf("%d\n",modify(l,r,x));
else printf("%d\n",modify(1,r,modify(l,n,x)));
}
}
int main(){
//File();
init();
work();
return 0;
}