记录编号 432022 评测结果 AAAAAAAAAA
题目名称 膜法师 最终得分 100
用户昵称 GravatarHzoi_Mafia 是否通过 通过
代码语言 C++ 运行时间 0.984 s
提交时间 2017-08-02 18:29:52 内存使用 51.81 MiB
显示代码纯文本
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>

#include<cstdlib>   //手动开栈真恶心= = 
using namespace std;
inline int read(){
	int sum(0);
	char ch(getchar());
	for(;ch<'0'||ch>'9';ch=getchar());
	for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
	return sum;
}
int n;
struct edge{
	int s,e,n;
}a[1000001];
int pre[1000001],tot;
inline void insert(int s,int e){
	a[++tot].s=s;
	a[tot].e=e;
	a[tot].n=pre[s];
	pre[s]=tot;
}
inline int my_max(int a,int b){
	return a>b?a:b;
}
inline int my_min(int a,int b){
	return a<b?a:b;
}
struct node{
	int id;
}hh[1000001];
bool die[1000001];
int target[1000001];
int ans_min(0),ans_max(0);
int in[1000001];
int low[1000001],dfn[1000001],zhan[1000001],bl[1000001],size[1000001];
int cnt,top,qlt;
bool vis[1000001];
int cl[1000001];
inline void tarjan(int u){
	dfn[u]=low[u]=++cnt;
	zhan[++top]=u;
	vis[u]=1;
	for(int i=pre[u];i!=-1;i=a[i].n){
		int e(a[i].e);
		if(!dfn[e]){
			tarjan(e);
			low[u]=my_min(low[u],low[e]);
		}
		else
			if(vis[e])
				low[u]=my_min(low[u],dfn[e]);
	}
	if(low[u]==dfn[u]){
		qlt++;
		while(1){
			int tmp(zhan[top--]);
			bl[tmp]=qlt;
			vis[tmp]=0;
			size[qlt]++;
			if(tmp==u)
				break;
		}
	}
}
inline bool cmp(node a,node b){
	if(cl[bl[a.id]]==cl[bl[b.id]])
		return in[a.id]<in[b.id];
	return cl[bl[a.id]]<cl[bl[b.id]];
}
queue<int>q;
int now(0x7fffffff),inf(0x7fffffff),fir;
int main(){
	freopen("maf.in","r",stdin);
	freopen("maf.out","w",stdout);
	
	int __size__=128<<20;
	char *__p__ =(char*)malloc(__size__)+__size__;
	__asm__("movl %0, %%esp\n"::"r"(__p__));
	
	memset(pre,-1,sizeof(pre));
	n=read();
	for(int i=1;i<=n;i++){
		hh[i].id=i;
		target[i]=read();
		if(target[i]==i){
			die[i]=1;
			bl[i]=++qlt;
			cl[qlt]=0;
			size[qlt]=1;
			ans_max++,ans_min++;
		}
	}
	for(int i=1;i<=n;i++){
		if(!die[i]&&!die[target[i]])
			insert(i,target[i]),in[target[i]]++;
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i]&&!die[i])
			tarjan(i);
	for(int i=1;i<=tot;i++){
		int s(a[i].s),e(a[i].e);
		s=bl[s],e=bl[e];
		if(s!=e)
			cl[s]=cl[e]=1;
	}
	for(int i=1;i<=qlt;i++){
		if(cl[i]==0&&size[i]>1){
			ans_max+=size[i]-1;
			ans_min+=(size[i]+1)>>1;
		}
	}
	sort(hh+1,hh+1+n,cmp);
	for(int i=1;i<=n;i++){
		int tmp(hh[i].id);
		if(cl[bl[tmp]]==1&&!in[tmp]){
			now=my_min(now,i);
			continue;
		}
		if(cl[bl[tmp]]==1&&in[tmp]){
			fir=i;
			break;
		}
	}
	if(now!=inf){
		ans_max+=n-fir+1;
		for(int i=now;i<fir;i++)
			q.push(hh[i].id);
		while(!q.empty()){
			int k(q.front());
			cl[bl[k]]=0;
			q.pop();
			int tar(target[k]);
			if(!die[tar]){
				die[tar]=1;
				cl[bl[tar]]=0;
				ans_min++;
				int kk(target[tar]);
				in[kk]--;
				if(!die[kk]&&!in[kk])
					q.push(kk);
			}
		}
	}
	for(int i=1;i<=cnt;i++)
		if(cl[i])
			ans_min+=(size[i]+1)>>1;
	printf("%d %d",ans_min,ans_max);
}