mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-11-06 14:53:47 +00:00
Compare commits
No commits in common. "779ef8b3279069c261ec426ce02ed0266c4b7c3d" and "32de376783da4c6954e22e4498aafce7bcde0ef3" have entirely different histories.
779ef8b327
...
32de376783
@ -1,115 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iostream>
|
|
||||||
#include <istream>
|
|
||||||
// 使用 long long 防止溢出,特别是 c_i 可以达到 2*10^18
|
|
||||||
using ll = long long;
|
|
||||||
|
|
||||||
#define sl static inline
|
|
||||||
|
|
||||||
const ll maxn = 100 + 5;
|
|
||||||
ll T, n;
|
|
||||||
// tc, tm 定义为 long long 以匹配 c_i 的数量级,防止计算中溢出
|
|
||||||
ll tc, tm;
|
|
||||||
ll a[maxn], b[maxn], c[maxn];
|
|
||||||
|
|
||||||
// 检查总花费 S 是否可行
|
|
||||||
// 替换了原来错误的 checkall 函数
|
|
||||||
sl bool checkall(ll S) {
|
|
||||||
// 设 cookie 制作时间减少 x,则 muffin 减少 S-x
|
|
||||||
// 我们需要寻找是否存在一个 x 满足所有约束
|
|
||||||
|
|
||||||
// 约束1: x 必须在花费和时间限制内
|
|
||||||
// x >= 0, S-x >= 0 => 0 <= x <= S
|
|
||||||
// tc - x >= 1 => x <= tc - 1
|
|
||||||
// tm - (S-x) >= 1 => x >= S - tm + 1
|
|
||||||
ll lower_x = std::max(0LL, S - tm + 1);
|
|
||||||
ll upper_x = std::min(S, tc - 1);
|
|
||||||
|
|
||||||
// 如果初始约束已经无解,则该 S 不可行
|
|
||||||
if (lower_x > upper_x) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 约束2: 满足所有朋友的时间要求
|
|
||||||
// a_i * (tc - x) + b_i * (tm - (S-x)) <= c_i
|
|
||||||
// (b_i - a_i) * x <= c_i - a_i*tc - b_i*tm + b_i*S
|
|
||||||
for (int i = 1; i <= n; ++i) {
|
|
||||||
// 使用 ll 处理中间计算,防止溢出
|
|
||||||
ll rhs = c[i] - a[i] * tc - b[i] * tm + b[i] * S;
|
|
||||||
|
|
||||||
if (a[i] < b[i]) {
|
|
||||||
// b_i - a_i > 0, x <= floor(rhs / (b_i - a_i))
|
|
||||||
// C++ 整数除法对于负数结果会向0取整,需要特殊处理
|
|
||||||
ll diff = b[i] - a[i];
|
|
||||||
ll new_upper;
|
|
||||||
if (rhs >= 0) {
|
|
||||||
new_upper = rhs / diff;
|
|
||||||
} else {
|
|
||||||
// 等价于 floor(x/y) 对于 x<0, y>0
|
|
||||||
new_upper = (rhs - diff + 1) / diff;
|
|
||||||
}
|
|
||||||
upper_x = std::min(upper_x, new_upper);
|
|
||||||
} else if (a[i] > b[i]) {
|
|
||||||
// b_i - a_i < 0, x >= ceil(rhs / (b_i - a_i))
|
|
||||||
// 两边同乘 -1,变为 (a_i - b_i) * x >= -rhs
|
|
||||||
// x >= ceil(-rhs / (a_i - b_i))
|
|
||||||
ll diff = a[i] - b[i];
|
|
||||||
ll neg_rhs = -rhs;
|
|
||||||
ll new_lower;
|
|
||||||
if (neg_rhs >= 0) {
|
|
||||||
// 等价于 ceil(x/y) 对于 x>=0, y>0
|
|
||||||
new_lower = (neg_rhs + diff - 1) / diff;
|
|
||||||
} else {
|
|
||||||
new_lower = neg_rhs / diff;
|
|
||||||
}
|
|
||||||
lower_x = std::max(lower_x, new_lower);
|
|
||||||
} else { // a[i] == b[i]
|
|
||||||
// x 的系数为 0,不等式变为 0 <= rhs
|
|
||||||
if (rhs < 0) {
|
|
||||||
// 此不等式无解,说明该总花费 S 不可行
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果所有约束下的 x 的可行范围存在 (即下界 <= 上界),则该 S 可行
|
|
||||||
return lower_x <= upper_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sl void solve() {
|
|
||||||
std::cin >> n >> tc >> tm;
|
|
||||||
for (ll i = 1; i <= n; i++) {
|
|
||||||
std::cin >> a[i] >> b[i] >> c[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 二分答案: 最小总花费
|
|
||||||
// 最小花费为 0, 最大花费为 tc+tm-2 (使制作时间都变为1)
|
|
||||||
ll left = 0, right = tc + tm - 2, ans = right + 1;
|
|
||||||
|
|
||||||
// 注意这里二分循环条件的修改
|
|
||||||
// [left, right] 是搜索区间
|
|
||||||
while (left <= right) {
|
|
||||||
ll mid = left + (right - left) / 2;
|
|
||||||
if (checkall(mid)) {
|
|
||||||
// 如果 mid 是一个可行的花费,我们记录它,并尝试寻找更小的花费
|
|
||||||
ans = mid;
|
|
||||||
right = mid - 1;
|
|
||||||
} else {
|
|
||||||
// 如果 mid 不可行,我们需要增加花费
|
|
||||||
left = mid + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << ans << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
std::ios_base::sync_with_stdio(false);
|
|
||||||
std::cin.tie(nullptr);
|
|
||||||
|
|
||||||
std::cin >> T;
|
|
||||||
while (T--) {
|
|
||||||
solve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
// 为了提高IO效率,这是OI/ACM竞赛中的常用技巧
|
|
||||||
#define FAST_IO std::ios_base::sync_with_stdio(false); std::cin.tie(NULL);
|
|
||||||
|
|
||||||
// 奶牛结构体,存储了所有必要信息
|
|
||||||
struct Cow {
|
|
||||||
int id; // 奶牛的原始输入编号 (0 to N-1)
|
|
||||||
long long x, y; // 初始坐标
|
|
||||||
char dir; // 方向 'N' 或 'E'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 交叉点/碰撞事件结构体
|
|
||||||
struct Intersection {
|
|
||||||
long long x, y; // 交叉点的坐标
|
|
||||||
int north_cow_id; // 参与该交叉点的北向牛的ID
|
|
||||||
int east_cow_id; // 参与该交叉点的东向牛的ID
|
|
||||||
|
|
||||||
// 重载小于运算符,为sort函数提供排序规则
|
|
||||||
// 这是这个算法思想的核心:按空间位置排序
|
|
||||||
bool operator<(const Intersection& other) const {
|
|
||||||
// 主关键字:按 x 坐标从小到大排序
|
|
||||||
if (x != other.x) {
|
|
||||||
return x < other.x;
|
|
||||||
}
|
|
||||||
// 次关键字:如果 x 相同,按 y 坐标从小到大排序
|
|
||||||
return y < other.y;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
FAST_IO;
|
|
||||||
|
|
||||||
int N;
|
|
||||||
std::cin >> N;
|
|
||||||
|
|
||||||
// 分别存储北向和东向的奶牛
|
|
||||||
std::vector<Cow> north_cows;
|
|
||||||
std::vector<Cow> east_cows;
|
|
||||||
// 使用一个vector来存储所有奶牛的原始信息,方便通过ID快速查找
|
|
||||||
std::vector<Cow> all_cows(N);
|
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
char dir;
|
|
||||||
long long x, y;
|
|
||||||
std::cin >> dir >> x >> y;
|
|
||||||
all_cows[i] = {i, x, y, dir};
|
|
||||||
if (dir == 'N') {
|
|
||||||
north_cows.push_back({i, x, y, dir});
|
|
||||||
} else {
|
|
||||||
east_cows.push_back({i, x, y, dir});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 步骤 1: 生成所有潜在的交叉点 ---
|
|
||||||
std::vector<Intersection> intersections;
|
|
||||||
for (const auto& n_cow : north_cows) {
|
|
||||||
for (const auto& e_cow : east_cows) {
|
|
||||||
// 一个北向牛和一个东向牛要相遇,必须满足几何条件:
|
|
||||||
// 北向牛在东向牛的右边 (n_cow.x > e_cow.x)
|
|
||||||
// 且北向牛在东向牛的下边 (n_cow.y < e_cow.y)
|
|
||||||
if (n_cow.x > e_cow.x && n_cow.y < e_cow.y) {
|
|
||||||
intersections.push_back({n_cow.x, e_cow.y, n_cow.id, e_cow.id});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 步骤 2: 按扫描线顺序对所有交叉点进行排序 ---
|
|
||||||
// 这是算法的关键!保证了我们总是处理路径上“最先”遇到的障碍
|
|
||||||
std::sort(intersections.begin(), intersections.end());
|
|
||||||
|
|
||||||
// --- 步骤 3: 模拟处理排序后的交叉点 ---
|
|
||||||
|
|
||||||
// `blame`数组既存储最终结果,也动态更新
|
|
||||||
// `blame[i]` = 牛i直接或间接阻挡的奶牛总数
|
|
||||||
std::vector<int> blame(N, 0);
|
|
||||||
// `stopped`数组标记一头牛是否已经停止
|
|
||||||
std::vector<bool> stopped(N, false);
|
|
||||||
|
|
||||||
for (const auto& intersect : intersections) {
|
|
||||||
int n_id = intersect.north_cow_id;
|
|
||||||
int e_id = intersect.east_cow_id;
|
|
||||||
|
|
||||||
// 如果参与这个交叉点的两头牛中,有任何一头已经停下了,
|
|
||||||
// 那么这个交叉点上的碰撞就不会发生,直接跳过。
|
|
||||||
if (stopped[n_id] || stopped[e_id]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算两头牛到达交叉点所需的距离(也即时间,因为速度为1)
|
|
||||||
long long dist_n = intersect.y - all_cows[n_id].y; // 北向牛需要向北走的距离
|
|
||||||
long long dist_e = intersect.x - all_cows[e_id].x; // 东向牛需要向东走的距离
|
|
||||||
|
|
||||||
if (dist_e < dist_n) { // 东向牛先到,阻挡北向牛
|
|
||||||
stopped[n_id] = true; // 北向牛被阻挡,标记为停止
|
|
||||||
|
|
||||||
// 关键的责备计算:
|
|
||||||
// 东向牛的责备数 += 1 (被它直接阻挡的北向牛) + 北向牛原本的责备数
|
|
||||||
// 这是一种动态规划的思想,利用了正确的处理顺序,
|
|
||||||
// 使得 `blame[n_id]` 此时已经包含了n_id能阻挡的所有下游奶牛。
|
|
||||||
blame[e_id] += 1 + blame[n_id];
|
|
||||||
|
|
||||||
} else if (dist_n < dist_e) { // 北向牛先到,阻挡东向牛
|
|
||||||
stopped[e_id] = true; // 东向牛被阻挡,标记为停止
|
|
||||||
|
|
||||||
// 同理,更新北向牛的责备数
|
|
||||||
blame[n_id] += 1 + blame[e_id];
|
|
||||||
}
|
|
||||||
// 如果 `dist_n == dist_e`,两牛同时到达,擦肩而过,互不影响,不做任何处理。
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 步骤 4: 输出结果 ---
|
|
||||||
// 按照原始输入顺序 (0 to N-1) 输出每头牛的责备数
|
|
||||||
for (int i = 0; i < N; ++i) {
|
|
||||||
std::cout << blame[i] << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
#include <cstdint>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
#include <istream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
|
||||||
using ll = int64_t;
|
|
||||||
#define sl static inline
|
|
||||||
ll T,n,arr[10],ans;
|
|
||||||
std::set<ll >v;
|
|
||||||
|
|
||||||
sl void solve(){
|
|
||||||
ans=0;
|
|
||||||
std::cin>>n;
|
|
||||||
v.clear();
|
|
||||||
for(ll i=1;i<=n;i++){
|
|
||||||
std::cin>>arr[i];
|
|
||||||
v.emplace(arr[i]);
|
|
||||||
}
|
|
||||||
for(ll i=1;i<=n;i++){
|
|
||||||
for(ll j=i+1;j<=n;j++){
|
|
||||||
v.emplace(std::abs(arr[i]-arr[j]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(auto a = v.begin();a!=v.end();a++){
|
|
||||||
for(auto b=a;b!=v.end();b++){
|
|
||||||
for(auto c=b;c!=v.end();c++){
|
|
||||||
for(ll i=1;i<=n;i++){
|
|
||||||
if(!(arr[i]==*a || arr[i]==*b || arr[i]==*c || arr[i]==*a+*b||arr[i]==*a+*c||arr[i]==*b+*c||arr[i]==*a+*b+*c)){
|
|
||||||
goto nxt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ans++;
|
|
||||||
nxt:;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout<<ans<<"\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
std::iostream::sync_with_stdio(false);
|
|
||||||
std::cin.tie(nullptr);
|
|
||||||
|
|
||||||
std::cin>>T;
|
|
||||||
while(T--){
|
|
||||||
solve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user