[WC2005]友好的生物

 

这题算是毒瘤吧,看到这个题我除了O(n^2)想不到别的方法

后来尝试使用平方的方式乱搞,但是给出了反例

在看了国家集训队ysy的解题报告后方才明白

思路是一种放宽的思路

我们枚举每个差值的符号,在其中枚举最大值,就可以有效去除绝对值

最后按照第k位从小到大排序,来枚举

从小到大进行扫描,每次用当前的值减去他前缀的最小值即可

但是在我看了部分题解后,我发现大家没有写什么要排序

而我就正好卡在这了,我太弱了

按照第k位从小到大排序,是为了后面的数第k种属性大于前面的

这样减出来第k个属性的差值一定是负值,满足条件

实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') p=-1,ch=getchar();
    while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar();
    return a*p;
}
const int N=100100;
int n,k,c[10],minn,num,ans,minid,t1,t2;
struct node
{
    int a[10],xu;
    bool operator < (const node &xx)const
    {
        return a[k]<xx.a[k];
    }
}po[N];
int main()
{
    // freopen("input","r",stdin);
    // freopen("output","w",stdout);
    n=read(),k=read();
    for(int i=1;i<=k;i++) c[i]=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=k;j++) po[i].a[j]=read()*c[j],po[i].xu=i;
    sort(po+1,po+1+n);
    for(int i=(1<<(k-1))-1;i>=0;i--)
    {
        minn=0x3f3f3f3f;
        for(int j=1;j<=n;j++)
        {
            num=0;
            for(int l=k-1;l>=1;l--) num+=(i&(1<<(l-1)))?-po[j].a[l]:po[j].a[l];
            num-=po[j].a[k];
            ans=max(ans,num-minn); if(ans==num-minn) t1=minid,t2=po[j].xu;
            minn=min(minn,num);if(minn==num) minid=po[j].xu;
        }
    }
    printf("%d %d\n%d",t1,t2,ans);
    return 0;
}
/*

*/

 

posted @ 2018-12-19 18:37  cold_cold  阅读(274)  评论(0编辑  收藏  举报