TopCoder SRM461C: FencingGarden 题解

我们首先可以发现一个性质:因为只会有两个小段是被切出来的,而篱笆有三条边,所以必然有一条边是由未被切割的篱笆构成的
我们设这条边的长度为x,所有篱笆的长度和为s,有两种情况
1. 这条边与墙平行,则面积S=xsx2=12x2+12sx
2. 这条边与墙垂直,则面积S=x(s2x)=2x2+sx
我们发现两种情况都是二次函数的形式,所以在顶点取到最大值
又因为x一定是整数,所以我要找的是用现在的这些木棍能拼出的小于顶点横座标的最大值和大于顶点横座标的最小值
考虑到n40 ,可以用一种很套路的折半搜索解决这个问题
我们先2n 枚举前二十个边,把所有可能的长度和存进一个set,然后再2n 枚举后二十条边,在set里面lower_bound一下就好了

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <utility>
#include <cctype>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#define LL long long
#define LB long double
#define x first
#define y second
#define Pair pair<int,int>
#define pb push_back
#define pf push_front
#define mp make_pair
#define LOWBIT(x) x & (-x)
using namespace std;

const int MOD=1e9+7;
const LL LINF=2e16;
const int INF=2e9;
const int magic=348;
const LB eps=1e-10;
const LB pi=3.14159265;

inline int getint()
{
    char ch;int res;bool f;
    while (!isdigit(ch=getchar()) && ch!='-') {}
    if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
    while (isdigit(ch=getchar())) res=res*10+ch-'0';
    return f?res:-res;
}

class FencingGarden
{
    LL sum,csum,llim,rlim;
    int a[48],b[48],atot,btot,n;
    set<LL> s;set<LL>::iterator iter;
    LB maxarea,curarea;
    LL maxlen,curlen;
    inline void check_max(LB curarea,LL curlen)
    {
        if (!curarea || !curlen) return;
        if (curarea>maxarea) {maxarea=curarea;maxlen=curlen;return;}
        if (curarea==maxarea) {maxlen=max(maxlen,curlen);}
    }
    inline void Clear()
    {
        atot=btot=0;
        sum=0;maxlen=maxarea=0;s.clear();
    }
    public:
        inline LL computeWidth(vector<int> segment)
        {
            int i,Mask;n=int(segment.size());Clear();
            for (i=0;i<int(segment.size());i++) sum+=segment[i];
            for (i=0;i<=n-1;i++) if (i<=n/2-1) a[++atot]=segment[i]; else b[++btot]=segment[i];
            for (Mask=0;Mask<=(1<<atot)-1;Mask++)
            {
                csum=0;
                for (i=1;i<=atot;i++) if (Mask&(1<<(i-1))) csum+=a[i];
                s.insert(csum);
            }
            if (sum%2==1) llim=sum/2,rlim=sum/2+1; else llim=rlim=sum/2;
            for (Mask=0;Mask<=(1<<btot)-1;Mask++)
            {
                csum=0;
                for (i=1;i<=btot;i++) if (Mask&(1<<(i-1))) csum+=b[i];
                LL nsum=llim-csum;iter=s.lower_bound(nsum);
                if (iter!=s.end() && (*iter)==nsum) {curlen=csum+(*iter);check_max((LB)(-(LB)curlen*curlen+(LB)sum*curlen)*1.0/2,curlen);}
                else if (iter!=s.begin()) {curlen=csum+(*(--iter));check_max((LB)(-(LB)curlen*curlen+(LB)sum*curlen)*1.0/2,curlen);}
                nsum=rlim-csum;iter=s.lower_bound(nsum);
                if (iter!=s.end())
                {
                    curlen=csum+(*iter);check_max((LB)(-(LB)curlen*curlen+(LB)sum*curlen)*1.0/2,curlen);
                }
            }
            if (sum%4==0) llim=rlim=sum/4; else llim=sum/4,rlim=sum/4+1;
            for (Mask=0;Mask<=(1<<btot)-1;Mask++)
            {
                csum=0;
                for (i=1;i<=btot;i++) if (Mask&(1<<(i-1))) csum+=b[i];
                LL nsum=llim-csum;iter=s.lower_bound(nsum);
                if (iter!=s.end() && (*iter)==nsum) {curlen=csum+(*iter);check_max((LB)(-2)*curlen*curlen+(LB)sum*curlen,sum-2*curlen);}
                else if (iter!=s.begin()) {curlen=csum+(*(--iter));check_max((LB)(-2)*curlen*curlen+(LB)sum*curlen,sum-2*curlen);}
                nsum=rlim-csum;iter=s.lower_bound(nsum);
                if (iter!=s.end())
                {
                    curlen=csum+(*iter);check_max((LB)(-2)*curlen*curlen+(LB)sum*curlen,sum-2*curlen);
                }
            }
            return maxlen;
        }
};

/*---Debug Part---*/
/*int main ()
{
    FencingGarden A;
    int nn;
    while (scanf("%d",&nn)!=EOF)
    {
        vector<int> vv;int x;
        while (nn--) x=getint(),vv.pb(x);
        cout<<A.computeWidth(vv)<<endl;
    }
    return 0;
}*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章