这道题思路很好想
但是实现实在是困难
主要是对于部分c的信息没有给出时
进行最小的字典序贪心处理
以及对于枚举的右端点在处理后的区间外部时
要进行特判,否则会将原本用来占位的位置算作贡献
不过这道题的数据特别水
我也没有特判什么就对了???
还有同学在找字典序最小的串时都写错了
但是还是A了
%%%
下面放代码
#include<bits/stdc++.h>
using namespace std;
int t,c,m,shu1,shu2,n,a[100005],dp[100005][4][2],ask[4][2],ans[5],temp[5];
void update()
{
bool flag=false;
for(int i=0;i<c;i++)
if(temp[i]>ans[i])
{
flag=false;
break;
}
else if(temp[i]<ans[i])
{
flag=true;
break;
}
if(flag)
for(int i=0;i<c;i++)
ans[i]=temp[i];
}
int main()
{
freopen("char.in","r",stdin);
freopen("char.out","w",stdout);
cin>>t>>c;
while(t--)
{
scanf("%d",&m);
memset(ans,127,sizeof(ans));
memset(a,-1,sizeof(a));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&shu1,&shu2);
n=max(n,shu1);
a[shu1]=shu2;
}
for(int i=0;i<c;i++)
dp[n+c][i][0]=n+c,dp[0][i][1]=0;//1 left to right
for(int i=n+c-1;i>=1;i--)//0 right to left
{
for(int j=0;j<c;j++)
{
dp[i][j][0]=dp[i+1][j][0];
}
if(a[i]!=-1)
{
dp[i][a[i]][0]=i;
}
}
for(int i=1;i<=n+c-1;i++)
{
for(int j=0;j<c;j++)
{
dp[i][j][1]=dp[i-1][j][1];
}
if(a[i]!=-1)
{
dp[i][a[i]][1]=i;
}
}
for(int len=c;len<=n+c-1;len++)
{
for(int i=0;i<c;i++)
ask[i][0]=len+1,ask[i][1]=0;
for(int l=1,r=len;l<=n+c-1;l+=len,r+=len)
{
for(int i=0;i<c;i++)
{
if(dp[l][i][0]<=r&&dp[l][i][0]!=n+c)
ask[i][0]=min(dp[l][i][0]-l+1,ask[i][0]);
if(r<=n+c-1)
if(dp[r][i][1]>=l)
ask[i][1]=max(dp[r][i][1]-l+1,ask[i][1]);
}
}
int now=0;
int pd=1;
for(int i=0;i<c;i++)
{
if(ask[i][0]==len+1)
{
now++;
temp[i]=1;
continue;
}
if(ask[i][0]<=now)
{
pd=0;
break;
}
temp[i]=ask[i][1]-now;
now=ask[i][1];
}
if(now<len) temp[c-1]+=len-now;
if(now>len) pd=0;
if(pd)
update();
}
if(ans[0]!=ans[4])
for(int i=0;i<c;i++)
printf("%d ",ans[i]);
else printf("NO");
printf("\n");
}
return 0;
}
/*
2 3
3
2 0
3 1
5 2
4
1 0
2 2
3 1
4 2
*/