BZOJ3716: [PA2014]Muzeum

一开始是懵逼的
因为不知道最大闭合子图能贪心
这个贪心是源于这个图的性质

为了方便计算我们需要吧每个守卫的视角做成直角 且两边平行于xy轴
然后根据y降序排序依次将守卫插入并将每个的手办贡献减一下就好了
实在不理解看代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<set>
#include<queue>
#include<cmath>
using namespace std;


struct Point
{
    long double  x,y;
    bool Checker;
    int Val;
    inline friend bool operator <(Point a,Point b)
    {
    return a.y>b.y||(
    abs(a.y-b.y)<1e-6&&a.x<b.x)||(
    abs(a.y-b.y)<1e-6&&
    abs(a.x-b.x)<1e-6&&a.Checker);  
    }
};
long double  w,h;
long double  s2=sqrt(2.000);
inline Point Flex(Point a)
{
    a.x=h/w*a.x;
    Point b;
    b=a;
    b.x=a.x*s2-a.y*s2;
    b.x/=2;
    b.y=a.x*s2+a.y*s2;
    b.y/=2;
    return b;
}
struct Node
{
    long double  x;
    int res;
    inline friend bool operator <(Node a,Node b)
    {return a.x>b.x||abs(b.x-a.x)<1e-6;}
};


Point L[1000001];
set<Node>Q;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    scanf("%Lf%Lf",&w,&h);
    long long ans=0;
    for(int i=1;i<=n;i++)
      scanf("%Lf%Lf%d",&L[i].x,&L[i].y,&L[i].Val),L[i].Checker=false,L[i]=Flex(L[i]),ans+=L[i].Val;
    for(int i=n+1;i<=n+m;i++)
      scanf("%Lf%Lf%d",&L[i].x,&L[i].y,&L[i].Val),L[i].Checker=true,L[i]=Flex(L[i]);
    n+=m;    
    set<Node>::iterator it;
    Node tp;
    sort(L+1,L+1+n);
    for(int i=1;i<=n;i++)
       if(L[i].Checker)
          if(!Q.count((Node){L[i].x,L[i].Val}))
           Q.insert((Node){L[i].x,L[i].Val});
          else
            {

                 it=Q.find((Node){L[i].x,L[i].Val});

                 tp=*it;
                 tp.res+=L[i].Val;
                 Q.insert(tp);  
            }
       else
         {
             it=Q.upper_bound((Node){L[i].x,L[i].Val});
             if(it==Q.end())continue;
             int k,tp=L[i].Val;
             Node ak;
             while(tp&&it!=Q.end())
                {
                    ans-=(k=min(tp,(*it).res));
                    ak=*it;
                    Q.erase(it);
                    ak.res-=k;
                    tp-=k;
                    if(ak.res)
                    {Q.insert(ak);break;}
                    it=Q.upper_bound((Node){L[i].x,L[i].Val});
                }
         } 
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(BZOJ3716: [PA2014]Muzeum)