CF45C Dancing Lessons 题解
CF45C Dancing Lessons 题解
不就是洛谷的 P1878 吗,雾。
暴力的时间复杂度是 \(O(n^2)\) 的,考虑优化。
考虑使用优先队列。内部存三个元素:绝对值、左边的孩子、右边的孩子。
这样我们重载运算符可以以绝对值为第一关键字,左边的孩子为第二关键字进行排序。
然后我们每次抽出来的一对小朋友他们的左边和右边都是有可能对答案产生贡献的,所以可以用链表进行维护。
最后还要判个重,这个打个标记即可。
还有不懂的就看代码吧。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,a[N];
bool kd[N],vis[N];
vector<pair<int,int> > ans;
struct LIST{
int l,r;
}lst[N];
struct NODE{
int val,l,r;
bool operator < (const NODE &x)const{
if(val!=x.val)
return x.val<val;
if(l!=x.l)
return x.l<l;
return x.r<r;
}
};
priority_queue<NODE> pq;
int main(){
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;++i)
{
char ch;cin>>ch;
if(ch=='B')kd[i]=1;
}
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=n;++i)//初始化链表
lst[i].l=i-1,lst[i].r=i+1;
// lst[1].l=n;lst[n].r=1;
// for(int i=lst[0].r;i;i=lst[i].r)cout<<lst[i].uid<<' ';
// cout<<'\n';
for(int i=1;i<n;++i)
if(kd[i]!=kd[i+1])
pq.push((NODE){abs(a[i]-a[i+1]),i,i+1});//初始值
while(!pq.empty())
{
int l=pq.top().l,r=pq.top().r;pq.pop();
if(vis[l]||vis[r])continue;
ans.push_back(make_pair(l,r));
vis[l]=vis[r]=1;
lst[lst[l].l].r=lst[r].r;
lst[lst[r].r].l=lst[l].l;
int x=lst[l].l,y=lst[r].r;
if(x<1||x>n||y<1||y>n)continue;//在链表中,1的左边是0,n的左边是n+1,不合法
if(kd[x]!=kd[y])
{
if(x<=y)
pq.push((NODE){abs(a[x]-a[y]),x,y});
else
pq.push((NODE){abs(a[x]-a[y]),y,x});
}
}
cout<<(int)ans.size()<<'\n';
for(int i=0;i<(int)ans.size();++i)
cout<<ans[i].first<<' '<<ans[i].second<<'\n';
return 0;
}

浙公网安备 33010602011771号