usaco 2018 open contest gold

http://www.usaco.org/index.php?page=open17results
总体难度不大,不过这次很奇怪,只有两道题。
A:
题意:2组,每组n个字符串,找出长度最小的区间满足字符串的这一段在组内可以重复但两组之间不能重复。
思路:二分答案,滚动哈希,用set维护一下。
B:
题意:n个0到n的数字,0表示空格,其他数字表示颜色。现在每轮可以找出不相交的一些区间涂上同一种颜色,一种颜色只能图一次,问最少可以用几轮把颜色涂好,并且0处不涂颜色。颜色可以覆盖。
思路:答案就是各种颜色最厚的地方的厚度,记录每一个颜色的最左,最右边出现位置,用类似差分的东西算出最厚的厚度。计算前先判断是否可以完成,可以用一个栈维护。如果这个颜色第一次出现就进栈,最后一次出现就出栈。如果要出栈的颜色不是栈顶就输出-1,计算答案过程中也判断一下0。

#include<cstdio>
#include<string>
#include<cstring>
#include<utility>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<algorithm>
#include<vector>
#include<iostream>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define inf 0x7fffffff
#define minn(x,y) x=min(x,y)
#define maxx(x,y) x=max(x,y)
using namespace std;
string s[510],t[510];
set<int> st;
ll mod=12345762435983ll;
ll hs[510],ht[510];
int a[100];
int main()
{
	int i,j,k,n,m,x,y,z;
	freopen("cownomics.in","r",stdin);
	freopen("cownomics.out","w",stdout);
	ll po;
	scanf("%d%d",&n,&m);
	a['A']=1;
	a['G']=2;
	a['C']=3;
	a['T']=4;
	for(i=0;i<n;i++)
	{
		cin>>s[i];
	}
	for(i=0;i<n;i++)
	{
		cin>>t[i];
	}
	int l,r,mid;
	l=0;r=m;
	bool bo,an;
	while(r-l>1)
	{
		po=1;
		mid=l+r>>1;
		for(i=1;i<mid;i++)
		{
			po=po*5;
			po=po%mod;
		}
		st.clear();
		for(i=0;i<n;i++)
		{
			hs[i]=0;
			for(j=0;j<mid;j++)
			{
				hs[i]=(hs[i]*5+a[s[i][j]])%mod;
			}
			st.insert(hs[i]);
		}
		bo=1;
		for(i=0;i<n;i++)
		{
			ht[i]=0;
			for(j=0;j<mid;j++)
			{
				ht[i]=(ht[i]*5+a[t[i][j]])%mod;
			}
			if(st.count(ht[i]))
			{
				bo=0;
			}
		}
		an=bo;
		if(an)
		{
			goto en;
		}
		for(i=1;i<m-mid+1;i++)
		{
			bo=1;
			st.clear();
			for(j=0;j<n;j++)
			{
				hs[j]-=po*a[s[j][i-1]];
				hs[j]=(hs[j]+5*mod)%mod;
				hs[j]=(hs[j]*5+a[s[j][i+mid-1]])%mod;
				st.insert(hs[j]);
			}
			for(j=0;j<n;j++)
			{
				ht[j]-=po*a[t[j][i-1]];
				ht[j]=(ht[j]+5*mod)%mod;
				ht[j]=(ht[j]*5+a[t[j][i+mid-1]])%mod;
				if(st.count(ht[j]))
				{
					bo=0;
				}
			}
			an=bo;
			if(an)
			{
				break;
			}
		}
		en:;
		if(an)
		{
			r=mid;
		}
		else
		{
			l=mid;
		}
	}
	printf("%d",r);
	return 0;
}

#include<cstdio>
#include<string>
#include<cstring>
#include<utility>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<algorithm>
#include<vector>
#include<iostream>
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define inf 0x7fffffff
#define minn(x,y) x=min(x,y)
#define maxx(x,y) x=max(x,y)
using namespace std;
int l[100010],r[100010],a[100010],s[100010],st[100010];
bool vis[100010];
int main()
{
	int i,j,k,n,m,x,y,z,t=0;
	freopen("art2.in","r",stdin);
	freopen("art2.out","w",stdout);
	scanf("%d",&n);
	memset(l,0x3f,sizeof(l));
	for(i=0;i<n;i++)
	{
		scanf("%d",&x);
		a[i]=x;
		l[x]=min(l[x],i);
		r[x]=max(r[x],i);
	}
	for(i=0;i<n;i++)
	{
		if(a[i]==0)
		{
			continue;
		}
		if(i==l[a[i]])
		{
			vis[a[i]]=1;
			st[t]=a[i];
			t++;
		}
		if(vis[a[i]]&&st[t-1]!=a[i])
		{
			printf("-1");
			return 0;
		}
		if(i==r[a[i]])
		{
			vis[a[i]]=0;
			t--;
		}
	}
	x=0;
	y=0;
	for(i=0;i<n;i++)
	{
		if(a[i]==0)
		{
			if(x)
			{
				printf("-1");
				return 0;
			}
			continue;
		}
		if(i==l[a[i]])
		{
			vis[a[i]]=1;
			x++;
			s[r[a[i]]]--;
		}
		y=max(y,x);
		x=x+s[i];
	}
	printf("%d",y);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值