既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的。
于是,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 else 65 { 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 ",ans); 76 return 0; 77 }