2019.01.20【TJOI2014】【BZOJ5158】【洛谷P3971】Alice and Bob(拓扑排序)(贪心)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86562237

BZOJ传送门

洛谷传送门


解析:

其实就是加了特技的拓扑排序。

首先我们肯定可以确定一些位置的大小关系,连边建图后肯定是一个DAG,这时候应该都想得到拓扑排序。

但是我们同时需要令 b b 序列之和尽量大,换句话说,就是大的数尽量向前放,小的数尽量向后放。

只需要在拓扑排序的时候加一个优先队列来维护就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc putchar
#define cs const

namespace IO{
	namespace IOONLY{
		cs int Rlen=1<<18|1;
		char buf[Rlen],*p1,*p2;
	}
	inline char get_char(){
		using namespace IOONLY;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re int num;
		re char c;
		while(!isdigit(c=gc()));num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

cs int N=100005;
int n,A[N];
int last[N],nxt[N<<1],to[N<<1],ecnt,deg[N];
inline void addedge(int u,int v){
	nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v;deg[v]++;
}

int dfn[N];
set<int> q;
inline void topsort(){
	for(int re i=1;i<=n;++i)if(!deg[i])q.insert(i);
	int topsort_clock=0;
	while(!q.empty()){
		int u=*q.begin();q.erase(q.begin());
		dfn[u]=n-(topsort_clock++);
		for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])
		if(0==--deg[v])q.insert(v);
	}
	
}

int a[N],len;
inline ll calc(){
	topsort();
	a[len=1]=dfn[n];
	ll ans=1;
	for(int re i=n-1;i;--i){
		int x=dfn[i];
		if(x>a[len]){
			a[++len]=x;
			ans+=len;
		}
		else {
			int pos=lower_bound(a+1,a+len+1,x)-a;
			a[pos]=x;
			ans+=pos;
		}
	}
	return ans;
}

int s[N];
signed main(){
	n=getint();
	for(int re i=1;i<=n;A[i++]=getint());
	for(int re i=1;i<=n;++i){
		if(s[A[i]])addedge(s[A[i]],i);
		if(A[i]>1)addedge(i,s[A[i]-1]);
		s[A[i]]=i;
	}
	cout<<calc();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/86562237
今日推荐