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);
}