1. 程式人生 > >2017 計蒜之道初賽第五場題解

2017 計蒜之道初賽第五場題解

A:水題,WA了三次。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        vector<int> a(m);
        for(auto &v:a) cin>>v;
        sort(a.begin(),a.end(),[](int a,int b){ return a>b; });
        int
k=1,ans=0; bool ok=false; if(n>1) for(int i=0;i<m&&a[i];i++) { k+=a[i]-1; ans=i+1; if(k>=n) break; } if(k>=n) cout << ans << endl; else cout << "Impossible"
<< endl; } return 0; }

B,C:
類似XDOJ的1175。
動態維護s上一個長度為k的區間內不同數字的個數及其數量。
複雜度為 O(nm)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=50007;
int s[N],t[N],tmp[N],n,m,c1[N],c2[N];
int main()
{
    int T;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf
("%d",&s[i]); scanf("%d",&T); while(T--) { scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d",&t[i]); memset(c2,0,sizeof(c2)); memset(c1,0,sizeof(c1)); int ans=0,num=0,res=0; for(int i=1;i<=m;i++) { if(!c2[t[i]]) ++num; ++c2[t[i]]; } for(int i=1;i<=m;i++) { if(c1[s[i]]==c2[s[i]]) --res; ++c1[s[i]]; if(c1[s[i]]==c2[s[i]]) ++res; } if(res==num) ++ans; for(int i=m+1;i<=n;i++) { if(c1[s[i]]==c2[s[i]]) --res; ++c1[s[i]]; if(c1[s[i]]==c2[s[i]]) ++res; if(c1[s[i-m]]==c2[s[i-m]]) --res; --c1[s[i-m]]; if(c1[s[i-m]]==c2[s[i-m]]) ++res; if(res==num) ++ans; } printf("%d\n",ans); } return 0; }

D:
考慮到 k<200000 ,且有 m 個詢問,那麼這 m 個詢問中,最多有 m 中不同的 k
因此離線處理,先讀入所有的詢問,然後對於長度 l ,將所有長度為 lt 丟入雜湊表中,hashvalue(t)=ti 。然後對 s 中所有長度為 l 的子串求出雜湊值,然後放到雜湊表裡查詢。
判斷 substr(s)t 相等,這裡用了兩個 vis 來處理。
維護 substr(s) 的雜湊值:hash[l,r]=hash[l1,r1]s[l1]+s[r]
把雜湊表的複雜度看成 O(1) 的話,演算法時間複雜度是 O(nm+k)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e5+7,N=5e4+7;
const int mod=M;
typedef vector<int> vi;
vector<int> s,t[M];
vector<int> T[N];
int ans[M],vis1[N],vis2[N],vs=1,c1[N],c2[N];
int n,m,L;

vector<vi> ht[mod];

bool iseq(vi &a,vi &b,int l)
{
    int cnt1=0,cnt2=0;
    for(auto &c : a)
    {
        if(vis1[c]!=vs)
        {
            vis1[c]=vs;
            c1[c]=1;
            ++cnt1;
        }
        else ++c1[c];
    }
    for(int i=0;i<a.size();i++)
    {
        int c=b[i+l];
        if(vis2[c]!=vs)
        {
            vis2[c]=vs;
            c2[c]=1;
        }
        else ++c2[c];
        if(vis1[c]==vs)
        {
            if(c1[c]==c2[c]) ++cnt2;
            else if(c1[c]==c2[c]-1) --cnt2;
        }
    }
    ++vs;
    return cnt1==cnt2;
}

void update(int hv,int l)
{
    for(auto &vec:ht[hv])
    {
        int j=vec[0];
        if(iseq(t[j],s,l))
        {
            for(auto &v:vec)
                ++ans[v];
            return ;
        }
    }
}
void insert(int id)
{
    int hv=0;
    for(int i=0;i<t[id].size();++i) hv=(hv+t[id][i])%mod;
    vi v;
    for(auto& vec:ht[hv])
    {
        int x=vec[0];
        if(iseq(t[x],t[id],0))
        {
            vec.push_back(id);
            return ;
        }
    }
    v.push_back(id);
    ht[hv].push_back(v);
}
int main()
{
    scanf("%d",&n);
    s=vector<int>(n);
    for(int i=0;i<n;i++)
        scanf("%d",&s[i]);
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        int k;
        scanf("%d",&k);
        t[i]=vector<int>(k);
        for(int j=0;j<k;++j) scanf("%d",&t[i][j]);
        T[t[i].size()].push_back(i);
    }
    for(int i=1;i<=n;++i)
    {
        if(!T[i].size()) continue;
        for(int j=0;j<mod;++j) ht[j].clear();
        for(auto j:T[i]) insert(j);
        int hv=0;
        L=t[T[i][0]].size();
        for(int j=0;j<L;++j) hv=(hv+s[j])%mod;
        update(hv,0);
        for(int j=L;j<n;++j)
        {
            hv=(hv-s[j-L]+mod)%mod;
            hv=(hv+s[j])%mod;
            update(hv,j-L+1);
        }
    }
    for(int i=0;i<m;i++)
        printf("%d\n",ans[i]);
    return 0;
}