小熊的果篮
提供一个考场上的奇怪做法。
考虑维护所有块,在块之间用链表连,每一块也拉个链表维护块内的元素。
每次如果有一块没了就暴力合并,这个复杂度我算不来,大概过不去。
考虑优化成启发式合并,复杂度就变成最多
code:
#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define Rep(i,l,r) for(int i=(l);i>=(r);--i)
using namespace std;
typedef deque<int> vec;
const int N=200005;
int n,a[N],cnt,nxt[N],pre[N];
vec block[N];
void merge(int x,int y){
if(block[x].size()<block[y].size()){
while(!block[x].empty())block[y].push_front(block[x].back()),block[x].pop_back();
pre[y]=pre[x];nxt[pre[x]]=y;
}else{
for(int t:block[y])block[x].push_back(t);
nxt[x]=nxt[y];pre[nxt[y]]=x;
}
}
int main(){
scanf("%d",&n);
rep(i,1,n)scanf("%d",&a[i]);
rep(i,1,n){
int t=a[i];cnt++;
while(i<=n&&a[i]==t)block[cnt].push_back(i),i++;
i--;
}
rep(i,1,cnt)pre[i]=i-1,nxt[i-1]=i;
nxt[cnt]=0,pre[0]=cnt;
while(nxt[0]){
for(int i=nxt[0];i;i=nxt[i])printf("%d ",block[i].front()),block[i].pop_front();
puts("");
for(int i=nxt[0];i;i=nxt[i])if(!block[i].size()){
bool domerge=0;int x=pre[i];
while(i&&!block[i].size())domerge=1-domerge,i=nxt[i];
if(!x){nxt[0]=i;pre[i]=0;continue;}
if(!i){nxt[x]=0;pre[0]=x;continue;}
if(!domerge)nxt[x]=i,pre[i]=x;
else merge(x,i);
}
}
return 0;
}