E. Segments Removal(优先队列&set)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Segments Removal(优先队列&set)相关的知识,希望对你有一定的参考价值。

E. Segments Removal(优先队列&set)

本题可用优先队列模拟,用 p a i r pair pair储存每段长度和编号,然后开两个数组 n e x t [ ] , p r e [ ] next[],pre[] next[],pre[]用来合并操作。至于合并后之前的两个已经被删除的段怎么处理,考虑用 s e t set set标记是否访问即可,或者也可以再开一个优先队列维护。

两pq+链表

// Problem: E. Segments Removal
// Contest: Codeforces - Codeforces Round #452 (Div. 2)
// URL: https://codeforces.ml/problemset/problem/899/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-08-25 23:29:48
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n;
priority_queue<PII>q,vis;
int nt[N],pre[N];
int a[N],b[N],cnt;
int main(){
	scanf("%d",&n);
	rep(i,1,n){
		int x;scanf("%d",&x);
		if(a[cnt]==x) b[cnt]++;
		else a[++cnt]=x,b[cnt]=1;
	}
	rep(i,1,cnt) q.push({b[i],-i}),nt[i]=i+1,pre[i]=i-1;
	int ans=0;
	while(cnt){
		while(!vis.empty()&&q.top()==vis.top()) q.pop(),vis.pop();
		int x=-q.top().se;q.pop();
		int u=pre[x],v=nt[x];
		nt[u]=v,pre[v]=u;
		if(u&&a[u]==a[v]){
			vis.push({b[u],-u}),vis.push({b[v],-v});
			b[u]+=b[v],nt[u]=nt[v],pre[nt[v]]=u;
			q.push({b[u],-u});
			cnt--;
		}
		cnt--;ans++;
	}
	printf("%d\\n",ans);
	return 0;
}

pq+set

// Problem: E. Segments Removal
// Contest: Codeforces - Codeforces Round #452 (Div. 2)
// URL: https://codeforces.ml/problemset/problem/899/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-08-25 23:29:48
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n;
priority_queue<PII>q;
set<PII>vis;
int nt[N],pre[N];
int a[N],b[N],cnt;
int main(){
	scanf("%d",&n);
	rep(i,1,n){
		int x;scanf("%d",&x);
		if(a[cnt]==x) b[cnt]++;
		else a[++cnt]=x,b[cnt]=1;
	}
	rep(i,1,cnt) q.push({b[i],-i}),nt[i]=i+1,pre[i]=i-1;
	int ans=0;
	while(cnt){
		while(vis.count(q.top())) q.pop();
		int x=-q.top().se;q.pop();
		int u=pre[x],v=nt[x];
		nt[u]=v,pre[v]=u;
		if(u&&a[u]==a[v]){
			vis.insert({b[u],-u}),vis.insert({b[v],-v});
			b[u]+=b[v],nt[u]=nt[v],pre[nt[v]]=u;
			q.push({b[u],-u});
			cnt--;
		}
		cnt--;ans++;
	}
	printf("%d\\n",ans);
	return 0;
}

以上是关于E. Segments Removal(优先队列&set)的主要内容,如果未能解决你的问题,请参考以下文章

E. Carrots for Rabbits(贪心+优先队列)

E. Carrots for Rabbits(贪心+优先队列)

E. Carrots for Rabbits(贪心+优先队列)

线段树or优先队列+dp E. Lunar New Year and Red Envelopes

E. Boring Segments(尺取&线段树)

cf1555 E. Boring Segments