CF 773 (Div. 1) D. Two Arrays 双指针 容斥

传送门

共有\(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;
}

posted @ 2024-08-10 15:22  chdy  阅读(5)  评论(0编辑  收藏  举报