Compare commits

..

No commits in common. "779ef8b3279069c261ec426ce02ed0266c4b7c3d" and "32de376783da4c6954e22e4498aafce7bcde0ef3" have entirely different histories.

3 changed files with 0 additions and 286 deletions

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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();
}
}