枚举几何
找坐位https://ac.nowcoder.com/acm/contest/33186/C
需要注意 因为是射线而且起点固定 所以每一行只有最前面的那一个位置的斜率是符合要求的 可使用单指针的枚举 计算两个顶点开始 每一行不被射线射到的位置向下取整即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int X[200007], Y[200007], Xrow[200007], Xgd0[200007], Xgdm[200007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, k, q;
cin >> n >> m >> k >> q;
for (int i = 1;i <= k;i++) cin >> X[i] >> Y[i];
while (q--) {
int id;
cin >> id;
cin >> X[id] >> Y[id];
for (int y = 1;y <= m;y++) Xrow[y] = n + 1;
for (int i = 1;i <= k;i++) Xrow[Y[i]] = min(Xrow[Y[i]], X[i]);///更新某行最靠前的人
double k = 0;
for (int y = 1;y <= m;y++) {
k = max(k, 1.0 * (y - 1) / Xrow[y]);///更新(0,1)射线最大斜率
if (k == 0) Xgd0[y] = Xrow[y] - 1;///斜率为0
else Xgd0[y] = 1.0 * (y - 1) / k - 1e-9;///(x,x+1] = x,最大斜率与第y行交点(可能超过n)
}
k = 0;
for (int y = m;y >= 1;y--) {
k = min(k, 1.0 * (y - m) / Xrow[y]);///更新(0,m)射线最小斜率
if (k == 0) Xgdm[y] = Xrow[y] - 1;
else Xgdm[y] = 1.0 * (y - m) / k - 1e-9;
}
ll ans = 0;
for (int y = 1;y <= m;y++) ans += min({ n,Xgd0[y],Xgdm[y] });
cout << ans << '\n';
}
return 0;
}