[NOI.AC#40]Erlang
阿新 • • 發佈:2018-10-25
最小 == line int const spa 一個數 noi register
鏈接
題解
顯然,最多抽2個集合
如果一直抽一個,前提是該集合有重復的,答案是不同元素的個數+1
如果抽兩個,那麽最壞情況下,在一個集合中抽到某一個數的次數是這個集合不同元素的個數(因為抽不到重復的)
枚舉其中一個集合 \(S\) ,對於每一種元素,令 \(f[i]\) 表示第 \(i\) 個元素在其他集合中最少要多少次抽到,將 \(f\) 數組從大到小排序,設 \(i\) 的排名為 \(rk_i\),那麽最壞情況下取 \(i\) 這個元素的條件是 在 \(S\) 中抽了 \(rk_i\) 次(如果超過 \(rk_i\) ,那麽之前一定抽到了比 \(f[i]\) 更小的)
因此,在所有情況下求最小值就是答案
復雜度 \(O(能過)\)
#include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) using namespace std; template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;} namespace IOManager{ const unsigned int iSize(131072); char buf[iSize],*iT=buf+iSize,*iS=iT-1; struct FastIO{ inline char gc(){ if(++iS==iT)fread(iS=buf,1,iSize,stdin);return *iS; } template<typename T> inline void read(T&w){register char c,p=0; while(isspace(c=gc()));if(c==‘-‘)p=1,c=gc();w=c^48u; while(isdigit(c=gc()))w=w*10+(c^48u);if(p)w=-w; } inline int read(){register int x;return read(x),x;} }; }IOManager::FastIO io; #define read io.read const int n=read(),N=5e5+5; vector<int>g[N]; int cnt[N],fi[N],se[N],a[N]; int main(){ int ans=1e9; memset(fi,0x3f,sizeof fi); REP(i,1,n){ int k=read(),s; g[i].resize(k); for(int&x:g[i])x=read(); sort(g[i].begin(),g[i].end()); g[i].resize(s=unique(g[i].begin(),g[i].end())-g[i].begin()); if(s<k)smin(ans,s+1); for(int x:g[i]){ if(s<fi[x])se[x]=fi[x],fi[x]=s; else if(s<se[x])se[x]=s; } } REP(i,1,n){ const int s=g[i].size();int k=0; for(int x:g[i])a[++k]=s==fi[x]?se[x]:fi[x]; sort(a+1,a+1+k,greater<int>()); REP(j,1,k)smin(ans,j+a[j]); } cout<<(ans==1e9?-1:ans); return 0; }
[NOI.AC#40]Erlang