洛咕 P4131 [WC2005]友好的生物
阿新 • • 發佈:2018-11-30
洛咕 P4131 [WC2005]友好的生物
首先可以發現\(C\)是沒有用的,可以乘進所有的權值裡面做
考慮沒有最後一維的限制,那麼兩個生物的友好值就是
\(\sum_{i=1}^k|a_i-b_i|\)
這個絕對值就很麻煩了。
但是可以換個思路想,既然是絕對值那麼一定\(\geq 0\),所以兩個生物的友好值是
\(\max\left(\sum_{i=1}^k(a_i-b_i)(-1)^{c_i}\right)\)
其中\(c\)取遍所有的01陣列。正確性是顯然的,因為其他的都沒有答案大。
那麼這道題\(k\leq 5\),不考慮最後一維就是\(k=4\)。
上面的式子分開來考慮:
\(\max\left(\sum_{i=1}^ka_i(-1)^{c_i}+\sum_{i=1}^kb_i(-1)^{c_i+1}\right)\)
那麼思路就很清晰了,對每個\(c\)記\(\max\left(\sum_{i=1}^kw_i(-1)^{c_i}\right)\)(記為\(Max_c\))以及取這個最大值的生物,
答案就是\(\max_{c_i+d_i=1}(Max_c+Max_d)\)
但是還有最後一維的限制,所以把生物按照最後一維排序,依次先和Max更新答案,再更新Max。在更新\(Max\)的時候減去最後一維更新,更新答案的時候加上最後一維
#include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } struct yyb{int a[4],b,i;}s[100010]; int S[100010][1<<4]; il bool operator<(const yyb&a,const yyb&b){return a.b<b.b;} int Mx[1<<4],f[1<<4],C[6]; int main(){ int n=gi(),k=gi(),U=(1<<4)-1; for(int i=0;i<k;++i)C[i]=gi(); for(int i=1;i<=n;++i){ for(int j=0;j<k-1;++j)s[i].a[j]=gi()*C[j]; for(int j=k-1;j<4;++j)s[i].a[j]=0; s[i].b=gi()*C[k-1]; s[i].i=i; } k=4; std::sort(s+1,s+n+1); for(int i=1;i<=n;++i) for(int j=0;j<1<<k;++j) for(int l=0;l<k;++l) if((1<<l)&j)S[i][j]+=s[i].a[l]; else S[i][j]-=s[i].a[l]; for(int i=0;i<1<<k;++i)Mx[i]=S[1][i]+s[1].b,f[i]=s[1].i; int ans=-1e9,a=0,b=0; #define chkans(t,_a,_b) {if((t)>ans)ans=(t),a=(_a),b=(_b);} if(a>b)std::swap(a,b); for(int i=2;i<=n;++i){ for(int j=0;j<1<<k;++j)chkans(Mx[U^j]+S[i][j]-s[i].b,s[i].i,f[U^j]); for(int j=0;j<1<<k;++j)if(Mx[j]<S[i][j]+s[i].b)Mx[j]=S[i][j]+s[i].b,f[j]=s[i].i; } printf("%d %d\n%d\n",a,b,ans); return 0; }