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;
}*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章