傳送門
共有\(n\)個向量,找兩個代價和最小且不存在任意元素相同的兩個向量。
本題特殊之處在於每個向量元素個數之多為\(5\)。
本題一個妙手是轉換成雙指標模型,按價值排序後,對於當前可行區間\(l,r\)隨著右端點的增大,左端點只有變小才有可能更新答案。
接下來考慮如何判斷\(1-l\)之中如何存在向量與\(a_r\)不衝突。
考慮容斥,對於\(a_r\)的\(2^m\)的子集查詢在其中出現次數\(c\),大小為\(w\),貢獻為\(c(-1)^w\)。由二項式定理可知若存在不衝突這個值應該不為0。
直接hash map會超時。
這裡有兩種策略一種是雙hash連結串列處理。一種是map標號,把向量從小到大排序後開5*n個map不斷的存下去一個向量鏈並標號。
由此複雜度降到了\(n2^m+nlogn\)。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x)
#define putl_(x) printf("%lld ",x)
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;i+=1)
#define fep(n,p,i) for(int i=n;i>=p;--i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define ui unsigned
#define sq sqrt
#define x(w) t[w].x
#define r(w) t[w].r
#define id(w) t[w].id
#define R(w) s[w].r
#define sum(w) t[w].sum
#define sc(A) scanf("%d",&A)
#define scl(A) scanf("%lld",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define sub(x,y) (x-y<0?x-y+mod:x-y)
#define uint unsigned int
#define mod 998244353
#define mod1 1000000007
#define zz p<<1
#define yy p<<1|1
using namespace std;
const int MAXN=100010,G=3,mol=10000007;
int n,m;
int a[MAXN][6];
int w[MAXN],p[MAXN];
int cmp(int a,int b){return w[a]<w[b];}
map<pair<int,int>,int>H;
int lin[mol],nex[mol*2],ver[mol*2],e[mol*2],len;
void add(int x,int y,int z)
{
ver[++len]=y;
nex[len]=lin[x];
e[len]=z;
lin[x]=len;
}
int find(int x,int y,int z)
{
go(x)
{
if(ver[i]==y)
{
e[i]+=z;
return e[i];
}
}
return -1;
}
void add(int d,int x,int v,int w,int w1)
{
if(d==m+1)
{
if(find(w,w1,v)!=-1)return;
add(w,w1,v);
return;
}
add(d+1,x,v,w,w1);
add(d+1,x,v,((ll)w*mod%mol+a[x][d])%mol,((ll)w1*13331%mod1+a[x][d])%mod1);
}
int cnt=0;
void dfs(int d,int x,int c,int w,int w1)
{
if(d==m+1)
{
int ww=find(w,w1,0);
ww=ww==-1?0:ww;
cnt+=(c&1)?-ww:ww;
return;
}
dfs(d+1,x,c,w,w1);
dfs(d+1,x,c+1,((ll)w*mod%mol+a[x][d])%mol,((ll)w1*13331%mod1+a[x][d])%mod1);
}
int ask(int x)
{
cnt=0;
dfs(1,x,0,0,0);
return cnt>0;
}
int b[MAXN][6];
int main()
{
int N;
sc(N);sc(m);
int ans=2000000010;
rep(1,N,i)
{
rep(1,m,j)sc(b[i][j]);
sort(b[i]+1,b[i]+1+m);
int flag=0,cost;
rep(2,m,j)if(b[i][j]==b[i][j-1])flag=1;
sc(cost);
if(!flag)
{
++n;
rep(1,m,j)a[n][j]=b[i][j];
w[n]=cost;p[n]=n;
}
}
//cout<<n<<endl;
sort(p+1,p+1+n,cmp);
int L=0;
rep(1,n,i)
{
if(w[p[i]]>ans)break;
if(!L)add(0,p[i],1,0,0);
if(i!=1)
{
if(L==0)
{
if(ask(p[i]))
{
L=i-1,add(0,p[L],-1,0,0);
add(0,p[i],-1,0,0);
}
}
}
while(L>=2&&ask(p[i]))
{
--L;
add(0,p[L],-1,0,0);
}
//cout<<i<<' '<<L<<endl;
if(L)ans=min(ans,w[p[i]]+w[p[L]]);
}
put(ans==2000000010?-1:ans);
return 0;
}