有人跟我一样zz用双端对列维护套个启发式合并吗? 我由于打错一个变量而与暴力老哥同分甚至还低。
#include<bits/stdc++.h>
using namespace std;
struct ljy{
int l,r;
}f[200010];
int a[200010],nxt[200010],pr[200010],totans,anss[200010];
deque<pair<int,int> >v[200010];
int main(){
freopen("fruit.in","r",stdin);
freopen("fruit.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int tot=1;
f[1].l=1;
for(int i=2;i<=n;i++){
if(a[i]!=a[i-1]){
f[tot].r=i-1;
f[++tot].l=i;
}
}
f[tot].r=n;
for(int i=1;i<=tot;i++)
v[i].push_back(make_pair(f[i].l,f[i].r));
int hd=1,tl=tot;
for(int i=1;i<=tot;i++){
pr[i]=i-1;
if(i!=tot)nxt[i]=i+1;
}
int ans=0,t=0;
while(ans<n){
t++;
int j=0,totans=0;
for(int i=hd;i;i=j){
anss[++totans]=v[i].front().first;
v[i].front().first++;
if(v[i].front().first>v[i].front().second)v[i].pop_front();
if(v[i].size()==0){
if(hd==i){
hd=nxt[hd];
pr[hd]=0;
j=hd;
}
else if(tl==i){
tl=pr[tl];
nxt[tl]=0;
j=0;
}
else{
int ad=nxt[i],ac=pr[i];
j=nxt[ad];
if(v[ad].front().first==v[ad].front().second){
anss[++totans]=v[ad].front().first;
v[ad].pop_front();
if(v[ad].size()==0){
if(ad==tl){
tl=ac;
nxt[tl]=0;
}
else{
nxt[ac]=nxt[ad];
pr[nxt[ad]]=ac;
}
continue;
}
}
else{
anss[++totans]=v[ad].front().first;
v[ad].front().first++;
}
if(v[ad].size()<v[ac].size()){
int len=v[ad].size();
for(int j=0;j<len;j++){
v[ac].push_back(v[ad].front());
v[ad].pop_front();
}
if(ad==tl){
tl=ac;//就是这里tl打成了hd,竟然还有30pts.
nxt[tl]=0;
}
else{
pr[nxt[ad]]=ac;
nxt[ac]=nxt[ad];
}
}
else{
int len=v[ac].size();
for(int j=0;j<len;j++){
v[ad].push_front(v[ac].back());
v[ac].pop_back();
}
if(ac==hd){
hd=ad;
pr[hd]=0;
}
else{
nxt[pr[ac]]=ad;
pr[ad]=pr[ac];
}
}
}
}
else j=nxt[i];
}
for(int i=1;i<totans;i++)
cout<<anss[i]<<" ";
cout<<anss[totans]<<"\n";
ans+=totans;
}
return 0;
}