首页 > 代码库 > 【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家

【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家

既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的。

于是,Splay、mutiset、权值分块什么的都支持查询后继呢。

 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 int Num,CH[12],f,c; 6 inline void R(int &x){ 7     c=0;f=1; 8     for(;c<0||c>9;c=getchar())if(c==-)f=-1; 9     for(x=0;c>=0&&c<=9;c=getchar())(x*=10)+=(c-0);10     x*=f;11 }12 long long ans;13 struct Val3{int c,v;bool is;void Read(){R(c);R(v);}}a[200001];14 struct Point{int v,p;}t[200001];15 bool operator < (const Val3 &a,const Val3 &b){return a.v!=b.v ? a.v>b.v : a.is>b.is;}16 bool operator < (const Point &a,const Point &b){return a.v<b.v;}17 int n,m,en,ma[200001],b[200001],sumv[450],l[450],r[450],num[200001],sum=1;18 int B[200001];19 void makeblock()20 {21     int sz=sqrt(en); if(!sz) sz=1;22     for(;sum*sz<en;++sum)23       {24           l[sum]=r[sum-1]+1; r[sum]=sum*sz;25           for(int i=l[sum];i<=r[sum];++i) num[i]=sum;26       }27     l[sum]=r[sum-1]+1; r[sum]=en;28     for(int i=l[sum];i<=r[sum];++i) num[i]=sum;29 }30 void Insert(const int &x){++B[x]; ++sumv[num[x]];}31 void Delete(const int &x){--B[x]; --sumv[num[x]];}32 int Next(const int &x)33 {34     for(int i=x;i<=r[num[x]];i++) if(B[i]) return i;35     for(int i=num[x]+1;i<=sum;i++) if(sumv[i])36       for(int j=l[i];j<=r[i];j++)37         if(B[j]) return j;38     return -1;39 }40 int main()41 {42     R(n); R(m);43     for(int i=1;i<=n;++i) a[i].Read();44     for(int i=n+1;i<=m+n;++i)45       {46           a[i].Read();47           a[i].is=1;48       }49     sort(a+1,a+n+m+1);50     for(int i=1;i<=m+n;++i)51       {52           t[i].v=a[i].c;53           t[i].p=i;54       }55     sort(t+1,t+1+n+m);56     ma[b[t[1].p]=++en]=t[1].v;57     for(int i=2;i<=n+m;++i)58       {59         if(t[i].v!=t[i-1].v) ++en;60         ma[b[t[i].p]=en]=t[i].v;61       } makeblock();62     for(int i=1;i<=n+m;++i)63       if(a[i].is) Insert(b[i]);64       else65         {66           int Nex=Next(b[i]);67           if(Nex==-1)68             {69               puts("-1");70               return 0;71             }72           ans+=(long long)ma[Nex];73           Delete(Nex);74         }75     printf("%lld\n",ans);76     return 0;77 }

【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家