题解 P6851 【onu】
yangwenbin · · 题解
题解 P6851 【onu】
P6851 onu
这道题是一道很典型的贪心的题目。
首先小 D 每一次出牌都会买等于自己牌面的糖果数
其次赢了还可以多拿到 c 个糖果 , 输了就失去 c 个糖果。
所以要赢,同时要赢得大。
这里就很像田忌赛马了。用自己小的和别人大的比,用大的去赢别人。
但这多一个颜色,就在排序贪心是,优先颜色(从小到大),其次牌面(从大到小)
操作时,先赢后输,先把能赢得都赢了,再考虑怎么输:
inline void win()
{
int i = 1,j = 1;
for (; i <= n; ++i)
{
if (put[i]) continue;
while (C[j].color < D[i].color && j <= m) ++j; // 调整颜色至两张牌颜色统一
for (;j <= m && D[i].color == C[j].color; ++j)
{
if (vis[j]) continue;// 如果这张牌用过了就跳过
if (D[i].num >= C[j].num) //能赢的最大的牌,赢掉这张,最大降低对方牌面大小
{
put[i] = vis[j] = true;
sum += (D[i].num + each);
ans[C[j].indax] = D[i].indax;
break;
}
}
}
return ;
}
然后考虑输的情况,大大牌肯定是要出的,小牌可以不出,
如果,小 D 的牌少,就输出 -1 ,所以
inline void lose()
{
int i = 1,j = 1;
for (; i <= n; ++i)
{
if (put[i]) continue;
while (C[j].color < D[i].color && j <= m) ++j;
for (;j <= m && D[i].color == C[j].color; ++j)
{
if (vis[j]) continue;
sum += (D[i].num - each);
put[i] = vis[j] = true;
ans[C[j].indax] = D[i].indax;
break;
}
}
for (int x = 1; x <= m; ++x)
{
if (vis[x]) continue;
sum -= each;
}
return ;
}
code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int SIZE = 1e5 + 50;
inline int read()
{
int x = 0,f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
f = (ch == '-' ? -1 : 1);
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return f * x;
}
int n,m,each,sum;
int color[SIZE],ans[SIZE];
bool vis[SIZE],put[SIZE];
struct onu
{
int color,num,indax;
};
onu C[SIZE],D[SIZE];
inline bool cmp(onu a,onu b)
{
return (a.color == b.color ? (a.num == b.num ? a.indax < b.indax : a.num > b.num) : a.color < b.color);
}
inline void get()
{
memset(ans,-1,sizeof(ans));
n = read();m = read();each = read();sum = read();
for (int i = 1; i <= n; ++i)
{
D[i].color = read();D[i].num = read();D[i].indax = i;
}
for (int i = 1; i <= m; ++i)
{
C[i].color = read();C[i].num = read();C[i].indax = i;
}
sort(C+1,C+1+m,cmp);sort(D+1,D+1+n,cmp);
}
inline void win()
{
int i = 1,j = 1;
for (; i <= n; ++i)
{
if (put[i]) continue;
while (C[j].color < D[i].color && j <= m) ++j;
for (;j <= m && D[i].color == C[j].color; ++j)
{
if (vis[j]) continue;
if (D[i].num >= C[j].num)
{
put[i] = vis[j] = true;
sum += (D[i].num + each);
ans[C[j].indax] = D[i].indax;
break;
}
}
// cout << D[i].indax << " " << D[i].num << " " << each << " " << sum << endl;
}
return ;
}
inline void lose()
{
int i = 1,j = 1;
for (; i <= n; ++i)
{
if (put[i]) continue;
while (C[j].color < D[i].color && j <= m) ++j;
for (;j <= m && D[i].color == C[j].color; ++j)
{
if (vis[j]) continue;
sum += (D[i].num - each);
put[i] = vis[j] = true;
ans[C[j].indax] = D[i].indax;
break;
}
// cout << D[i].indax << " " << D[i].num << " " << each << " " << sum << endl;
}
for (int x = 1; x <= m; ++x)
{
if (vis[x]) continue;
sum -= each;
}
return ;
}
inline void output()
{
printf("%lld\n",sum);
for (int i = 1; i <= m; ++i)
{
printf("%lld\n",ans[i]);
}
return ;
}
inline void solve()
{
win();
lose();
return ;
}
signed main()
{
get();
solve();
output();
return 0;
}