P13305 [GCJ 2013 Finals] Can't Stop 解题报告

简要题意

给定 \(n\)\(D\) 元组,求出最长的连续区间使得可以选出 \(k\) 个数满足区间内任意一个四元组中有至少一个元素为这 \(k\) 个数之一。

数据范围: \(n \le 10^5,2\le k \le 3,1 \le D \le 4\)

分析

首先,我们可以考虑一个极暴力的算法:枚举每一个位置,从当前位置开始,我们可以先从开始位置的多元组中钦定一个数作为当前选择的数,然后在不钦定新的数的前提下向右扩展;如果在 \(i\) 位置我们不能继续扩展,那么我们就从 \(i\) 位置的数中钦定一个数作为当前选择的数,然后继续扩展。

因为确定了开始位置和选择数字集就可以唯一确定不能继续扩展的位置,所以从一个位置出发扩展的时间复杂度是 \(O(nD^k)\),总时间复杂度 \(O(n^2D^k)\)

接下来考虑优化:

有一个人类智慧结论:从 \(i\) 开始扩展时,每一次选新的数时都保证 \(i-1\) 的多元组中不包含该数,那么每一个位置只会被访问 \(O(1)\) 次,且答案不会变劣。

首先证明“答案不会变劣”:这是显然的,因为如果选择 \(i-1\) 的多元组中有的数,那么从 \(i-1\) 开始扩展得到的答案会更优。

其次证明“每一个点只被访问 \(O(1)\) 次”:考虑从每一个位置 \(i\) 开始向左模拟上述形式扩展,那么有且仅有 \(i\) 向左不能继续扩展的位置可以在向右扩展中扩展到 \(i\)。因为如果存在一个位置 \(x\) 不满足这个条件,那么当 \(x\) 扩展到 \(i\) 时(选用 \(i\) 扩展到 \(x\) 时的相同数集),就一定会选到 \(x-1\) 中有的数。由于从 \(i\) 出发一共只有 \(\sum \limits_{i=0}^{k} D^i\) 种选数方案(可以不选够 \(k\) 次,也可以不选),因此每个位置只会被访问 \(O(1)\) 次。

Q.E.D.

优化后时间复杂度为 \(O(nD^k)\),模拟即可。

代码

const int N=1e5+100;
int T,n,d,k,a[N][5],b[5],ans,vis[N],st,ed;
void dfs(int u,int cnt,int len){
    if(u==n+1){
        if(len>ans) st=u-len+1,ed=u-1,ans=len;
        return;
    }
    int flag=0;
    For(i,1,d)
        if(vis[a[u][i]]==1){
            flag=1;
            break;
        }
    if(flag){
        dfs(u+1,cnt,len+1);
        return;
    }
    if(!flag && cnt==k){
        if(len>ans) st=u-len+1,ed=u-1,ans=len;
        return;
    }
    For(i,1,d)
        if(vis[a[u][i]]!=-1){
            vis[a[u][i]]=1;
            dfs(u+1,cnt+1,len+1);
            vis[a[u][i]]=0;
        }
}
int testcase;
void solve(){
    n=read(),d=read(),k=read();
    ans=0;
    For(i,1,n)
        For(j,1,d)
           a[i][j]=read();
    For(i,1,n){
        For(j,1,d)
            vis[a[i-1][j]]=-1;
        dfs(i,0,1);
        For(j,1,d)
            vis[a[i-1][j]]=0;
    }
    printf("Case #%d: %d %d\n",++testcase,st-1,ed-1);
}
int main()
{
#if !ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif 
    T=read();
    while(T--) solve();
    return 0;
}
posted @ 2025-08-21 12:21  XiaoZi_qwq  阅读(11)  评论(0)    收藏  举报