~~~题面~~~

题解:

  首先观察题面,直觉上对于一头奶牛,肯定要给它配pi和qi符合条件的草中两者尽量低的草,以节省下好草给高要求的牛。

  实际上这是对的,但观察到两者尽量低这个条件并不明确,无法用于判断,因此要考虑一些其他的方法。

  首先我们把牛和草都放在一个数组里,然后按照口感给它们排序。这样对于任意一头牛而言,口感符合要求的就只有在它前面的草。

  排完序后,我们只需要在任意一头牛之前找到一个还没有被分配的,价格最低的符合要求的草即可。

  为什么这样就不用考虑口感尽量低这个条件了呢?

  因为对于后面的任意一只牛而言,在它前面的草的口感值大于要求,因此不管前面的牛怎么选择,剩下的草都是符合口感要求的,因此此时再去对口感值做限制就毫无意义了。

  所以我们只需要在它前面的草中筛选出大于价格要求的,最便宜的草即可。

  如果没有大于价格要求这一条件,显然我们可以用堆,但是由于这个条件限制,堆无法实现。

  因此我们可以考虑用平衡树来实现它。

  用STL是最简单的,当然也可以自己手写。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 220000
#define LL long long int n, m, cnt;
LL ans; struct node{
int cost, taste;
bool who;
}p[AC]; struct splay_tree{
int root, tot, go;
int son[AC][], father[AC], cnt[AC], Size[AC], val[AC]; inline void update(int x)
{
Size[x] = Size[son[x][]] + Size[son[x][]] + cnt[x];
} void rotate(int x)
{
int y = father[x];
int z = father[y];
int k = (son[y][] == x);
father[x] = z;
son[z][son[z][] == y] = x;
father[son[x][k ^ ]] = y;
son[y][k] = son[x][k ^ ];
father[y] = x;
son[x][k ^ ] = y;
update(y), update(x);
} void splay(int x, int goal)
{
if(!x) return ;
while(father[x] != goal)
{
int y = father[x], z = father[y];
if(z != goal)
(son[y][] == x) ^ (son[z][] == y) ? rotate(x) : rotate(y);
rotate(x);
}
update(x);
if(!goal) root = x;
} void find(int x, int w)//找到这个点的前驱,并splay到root
{
if(!x) return ;
if(val[x] >= w)
{
if(!go || val[x] < val[go]) go = x;
find(son[x][], w);
}
else find(son[x][], w);
} int found(int k)//找根的前驱后继
{
int now = root;
now = son[now][k];
while(son[now][k ^ ]) now = son[now][k ^ ];
return now;
} void get(int x)
{
go = , find(root, x);
if(!go)
{
printf("-1\n");
exit();
}
splay(go, );
ans += val[go];
if(cnt[go] > )
{
--cnt[go];
update(go);
return ;
}
int before = found(), behind = found();
if(!before && !behind) root = ;
else if(!before) root = son[root][], father[root] = ;
else if(!behind) root = son[root][], father[root] = ;
else splay(before, ), splay(behind, before);
son[behind][] = ;
} void insert(int x)//插入一个点
{
int now = root, fa = ;
while(now && val[now] != x)
{
fa = now;
now = son[now][x > val[now]];
}
if(now) cnt[now] ++;
else
{
now = ++ tot;
if(fa) son[fa][x > val[fa]] = now;
father[now] = fa;
val[now] = x;
cnt[now] = Size[now] = ;
if(fa) update(fa);
}
splay(now, );
}
}s; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline bool cmp(node a, node b)
{
if(a.taste != b.taste) return a.taste > b.taste;
else return a.cost > b.cost;
} void pre()
{
int a, b;
n = read(), m = read();
for(R i = ; i <= n; i ++)
{
a = read(), b = read();
p[++cnt] = (node){a, b, };
}
for(R i = ; i <= m; i ++)
{
a = read(), b = read();
p[++cnt] = (node){a, b, };
}
sort(p + , p + cnt + , cmp);
// for(R i = 1; i <= cnt; i ++)
// printf("%d %d %d\n", p[i].cost, p[i].taste, p[i].who);
} void work()
{
for(R i = ; i <= cnt; i ++)
if(!p[i].who) s.get(p[i].cost);
else s.insert(p[i].cost);
printf("%lld\n", ans);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}
05-11 19:34