您的位置:首页 > 其它

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

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

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

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int Num,CH[12],f,c;
inline void R(int &x){
c=0;f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0');
x*=f;
}
long long ans;
struct Val3{int c,v;bool is;void Read(){R(c);R(v);}}a[200001];
struct Point{int v,p;}t[200001];
bool operator < (const Val3 &a,const Val3 &b){return a.v!=b.v ? a.v>b.v : a.is>b.is;}
bool operator < (const Point &a,const Point &b){return a.v<b.v;}
int n,m,en,ma[200001],b[200001],sumv[450],l[450],r[450],num[200001],sum=1;
int B[200001];
void makeblock()
{
int sz=sqrt(en); if(!sz) sz=1;
for(;sum*sz<en;++sum)
{
l[sum]=r[sum-1]+1; r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
}
l[sum]=r[sum-1]+1; r[sum]=en;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
}
void Insert(const int &x){++B[x]; ++sumv[num[x]];}
void Delete(const int &x){--B[x]; --sumv[num[x]];}
int Next(const int &x)
{
for(int i=x;i<=r[num[x]];i++) if(B[i]) return i;
for(int i=num[x]+1;i<=sum;i++) if(sumv[i])
for(int j=l[i];j<=r[i];j++)
if(B[j]) return j;
return -1;
}
int main()
{
R(n); R(m);
for(int i=1;i<=n;++i) a[i].Read();
for(int i=n+1;i<=m+n;++i)
{
a[i].Read();
a[i].is=1;
}
sort(a+1,a+n+m+1);
for(int i=1;i<=m+n;++i)
{
t[i].v=a[i].c;
t[i].p=i;
}
sort(t+1,t+1+n+m);
ma[b[t[1].p]=++en]=t[1].v;
for(int i=2;i<=n+m;++i)
{
if(t[i].v!=t[i-1].v) ++en;
ma[b[t[i].p]=en]=t[i].v;
} makeblock();
for(int i=1;i<=n+m;++i)
if(a[i].is) Insert(b[i]);
else
{
int Nex=Next(b[i]);
if(Nex==-1)
{
puts("-1");
return 0;
}
ans+=(long long)ma[Nex];
Delete(Nex);
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: