USACO Feburary Contest 比赛记录

A Timeline

题面

现在有 (n) 个事件,已知事件 (i) 在第 (S_i) 天及以后发生。除此之外,有 (C) 个关系 ((a,~b,~x)),要求事件 (b) 至少在 (a) 发生 (x) 天后发生。

求满足上述事件时各个事件发生的最早时间。

题解

topsort。

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
const int MAXN=200000+5+5;
struct Edge{int u,v,w,next;};
struct data
{
	int u,w;
	bool operator < (const data &b) const
	{
		return w==b.w?u<b.u:w>b.w;
	}
};
Edge edge[MAXN];
bool vis[MAXN];
int n,m,c,begin[MAXN],super,u,v,w,head[MAXN],dis[MAXN],cnt,in[MAXN];
std::queue<int>que;
void AddEdge(int u,int v,int w)
{
	edge[++cnt].u=u;edge[cnt].v=v;edge[cnt].w=w;
	edge[cnt].next=head[u];head[u]=cnt;
}
void BFS()
{
	que.push(super);
	while(!que.empty())
	{
		int u=que.front();que.pop();
		for(int i=head[u];i;i=edge[i].next)
		{
			dis[edge[i].v]=std::max(dis[edge[i].v],dis[edge[i].u]+edge[i].w);
			in[edge[i].v]--;
			if(!in[edge[i].v]) que.push(edge[i].v);
		}
	}
}
int main()
{
	freopen("timeline.in","r",stdin);
	freopen("timeline.out","w",stdout);
	scanf("%d %d %d",&n,&m,&c);
	super=n+1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&begin[i]);
		AddEdge(super,i,begin[i]);
		in[i]++;
	}
	for(int i=1;i<=c;i++)
	{
		scanf("%d %d %d",&u,&v,&w);
		in[v]++;
		AddEdge(u,v,w);
	}
	BFS();
	for(int i=1;i<=n;i++)
		printf("%d
",dis[i]);
	return 0;
}

B Help yourself

题面

给出 (N) 条线段,定义线段的并集和复杂度,求 (2^N) 条线段复杂度之和。

题解

实际上推导了一部分正解。但只写出了前几个点要了个部分分。

Code

#include<cstdio>
#include<map>
const int MAXN=100000+5;
int n,l[MAXN],r[MAXN],belong[MAXN],ans=0,cnt;
void search(int now)
{
	std::map<int,int>map;
	if(now==n+1)
	{
		for(int i=1;i<=n;i++)
			if(belong[i])map[belong[i]]++;
		ans=(ans+map.size())%1000000007;
		return;
	}
	search(now+1);
	int temp[30];
	temp[0]=cnt;
	for(int i=1;i<=n;i++)
		temp[i]=belong[i];
	for(int i=1;i<=n;i++)
	{
		if(now==i||!belong[i]) continue;
		if((l[now]>=l[i]&&l[now]<=r[i])||(r[now]>=l[i]&&r[now]<=r[i])||(l[now]<=l[i]&&r[now]>=r[i])) map[belong[i]]++;
	}
	if(!map.size()) belong[now]=++cnt;
	if(map.size()==1) belong[now]=map.begin()->first;
	if(map.size()>1)
	{
		belong[now]=++cnt;
		for(int i=1;i<=n;i++)
			if(map[belong[i]])
			{
				belong[i]=cnt;
			}
	}
	search(now+1);
	for(int i=1;i<=n;i++)
		belong[i]=temp[i];
	cnt=temp[0];
}
int main()
{
	freopen("help.in","r",stdin);
	freopen("help.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d %d",&l[i],&r[i]);
	search(1);
	printf("%d",ans);
	return 0;
}
无特别声明的情况下,本文为原创文章,允许转载,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
在声明禁止转载的情况下,请勿转载;若本文章为转载的文章,版权归原作者所有。
如果您觉得本文写得好,请点击下方的推荐按钮~若您有任何建议和指正,请在下方留言,对于您的指正将不胜感激。
原文地址:https://www.cnblogs.com/ksyx/p/USACO-Feb20.html