月赛C求助
查看原帖
月赛C求助
315191
P31pr楼主2021/5/2 09:01

思路是只计算每个人一血将要杀别人时杀他的贡献,方案数是区间长度。

#include<cstdio>
#include<cstring>
#include<cctype>

#define re register
#define il inline

il int read()
{
	re int x=0;
	char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch))
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x;
}

const int N=6e4+5,M=1e3+5;

int n,m;
int u[N],v[N];
int h[M],th[M];
int r,ans[M];//r是不操作时最终存活人数

void reseth()
{
	for(int i=1;i<=m;++i)
		h[i]=3;
}
void resett()
{
	for(int i=1;i<=m;++i)
		th[i]=3;
}
int cal(int t,int s)
{
	resett();
	int res=m;
	for(int k=1;k<=n;++k)
	{
		if(th[u[k]]&&th[v[k]])
		{
			th[v[k]]--;
			if(!th[v[k]]) res--;
		}
		if(k==t-1)
			th[s]--,res--;
	}
//	printf("cal(%d,%d)=%d\n",t,s,res);
	return res;
}

int main()
{
	n=read(),m=read();
	reseth();
	r=m;
	for(int i=1;i<=n;++i)
	{
		u[i]=read(),v[i]=read();
		if(h[u[i]]&&h[v[i]])
		{
			h[v[i]]--;
			if(!h[v[i]]) r--;
		}
	}
	for(int i=1;i<=m;++i)
	{
		int pre=0;
		reseth();
		for(int k=1;k<=n;++k)
		{
			if(h[u[k]]&&h[v[k]])
				h[v[k]]--;
			if(h[i]==1&&u[k]==i)
			{
				ans[cal(k,i)]+=k-pre;
				pre=k;
			}
		}
		if(h[i]==1) ans[r-1]+=n+1-pre;
		if(!h[i]||h[i]>1) ans[r]+=n+1-pre;
	}
	for(int i=0;i<=m;++i)
		printf("%d ",ans[i]);
	return 0;
}

甚至过了自己的手造样例:

3 9
1 2
1 2
2 3
2 3
3 1
3 1
1 2
2 3
3 1
2021/5/2 09:01
加载中...