1. 程式人生 > >[loj2736][JOISC 2016 Day3]回轉壽司——分塊+堆

[loj2736][JOISC 2016 Day3]回轉壽司——分塊+堆

題目大意:

給出一個有 NN 個點的環,環上各點有一個初始權值aia_i。 給出 QQ 個詢問,每次詢問給出一個區間 [l,r][l,r] 和一個值 AA ,對於 AA 的變動定義如下(rr 可能會小於 ll 因為是環形):

for (int i = l; i <= r; i++) if(a[i] > A) swap(a[i],A);

對於每個詢問,回答遍歷完區間 [l,r][l,r]AA 的最終值。 注:我們按逆時針方向在環上編號,並規定 [l,r][l,r]為從位置編號為 ll 的點逆時針遍歷至位置編號為 rr 的點所經過點的集合。

思路:

這種看起來怎麼都不好做的題目考慮分塊。 對於這個操作,我們對於每一塊顯然只需要取出其中最大的元素即可,用一個堆來維護每一個塊的中的元素。 但是對於邊角塊,修改的時候可以暴力修改,可我們也需要知道每一個元素的具體位置,於是這裡有了一種重構的操作: 我們將每一次放入這個塊內的元素記錄下來,按照從小到大的順序進行那種交換的操作,只考慮最終的結果,不難發現這樣是正確的,用一個小根堆維護即可。 時間複雜度Θ(nnlogn)\Theta(n\sqrt {n}\log n)

#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; }