A.订单
按ai排序,看到ai天时货物够不够
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e2 + 7;
pair<int,int> p[N];
int n,k;
void solve(){
cin >> n >> k;
for(int i = 1;i <= n;i ++) cin >> p[i].first >> p[i].second;
int sum = 0;
sort(p + 1,p + n + 1);
for(int i = 1;i <= n;i ++){
sum += (p[i].first - p[i - 1].first) * k;
sum -= p[i].second;
if(sum < 0){
cout << "No" << endl;
return;
}
}
cout << "Yes" << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; cin >> t;
while(t --){
solve();
}
return 0;
}
B.建筑公司
首先可以记录一下当前公司有的各类员工人数
然后再将项目人数大于公司现有各类员工人数的记录一下 并且将此项目+n 表示所需的n类的员工不够
然后再记录一下完成后会带来的员工人数 并且将能直接完成的项目入队
然后就是再队列中不断更新现有员工人数 并且每一项员工人数够就入队
code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N = 1e5 + 7;
int st[N];//记录每一个项目有几个工人不满足当前公司现有情况
void solve(){
int g; cin >> g;
map<int,int> now;
for(int i = 1;i <= g;i ++){
int t,u; cin >> t >> u;
now[t] += u;
}
int n; cin >> n;
map<int,priority_queue<PII,vector<PII>,greater<PII>>> suf;//不满足当前员工人数的项目的所差数
map<int,vector<PII>> add;
queue<int> q;
for(int i = 1;i <= n;i ++){
int m1; cin >> m1;
for(int j = 1;j <= m1;j ++){
int a,b; cin >> a >> b;
if(now[a] >= b) continue;
suf[a].push({b,i});
st[i] ++;
}
int m2; cin >> m2;
for(int j = 1;j <= m2;j ++){
int c,d; cin >> c >> d;
add[i].push_back({c,d});
}
if(!st[i]) q.push(i);
}
int ans = 0;
while(q.size()){
auto t = q.front();
q.pop();
ans ++;
for(auto x : add[t]){
now[x.first] += x.second;
while(suf[x.first].size()){
if(suf[x.first].top().first > now[x.first]) break;
st[suf[x.first].top().second] --;
if(!st[suf[x.first].top().second]) q.push(suf[x.first].top().second);
suf[x.first].pop();
}
}
}
cout << ans << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; t = 1;
while(t --){
solve();
}
return 0;
}
D.负重越野
二分答案x
那么vi - (wj - wi) >= x 即 vi + wi - x >= wj
所以check就可以:
- 将 vi >= x 存一块 存为 vi + wi - x 命名为 1
- 将vi < x 存一块 命名为 2
然后sort后分别比较 1 和 2 最大的 看是否可以符合二分的答案 x
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 7;
pair<int,int> p[N];
int st[N];
int n;
int check(int x){
vector<int> v1,v2;
for(int i = 0;i < n;i ++){
if(p[i].first >= x) v1.push_back(p[i].first + p[i].second - x);
else v2.push_back(p[i].second);
}
sort(v1.begin(),v1.end());
sort(v2.begin(),v2.end());
if(v2.size() > v1.size()) return 0;
int len1 = v1.size(),len2 = n - len1;
for(int i = len1 - 1;i >= 0;i --){
if(!len2) break;
len2 --;
if(v1[i] < v2[len2]) return 0;
}
return 1;
}
void solve(){
cin >> n;
for(int i = 0;i < n;i ++) cin >> p[i].first >> p[i].second;
sort(p,p + n);
int l = -1,r = p[n - 1].first + 1;
while(l + 1 != r){
int mid = l + r >> 1;
if(check(mid)) l = mid;
else r = mid;
}
cout << l << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; cin >> t;
while(t --){
solve();
}
return 0;
}
E.数学问题
易看出应该先除后乘 不然乘的最后会被除掉 (n * k + x) / k = n * k / k + x / k (x < k) = n
然后枚举次数即可 并且乘时候看一下边界即可知道有无m的倍数 取最小val
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
void solve(){
int n,k,m,a,b; cin >> n >> k >> m >> a >> b;
if(n % m == 0){
cout << 0 << endl;
return;
}
if(k == 1){
cout << -1 << endl;
return;
}
int mn = 1e18;
for(int i = 0;;i ++){
if(n == 0){
mn = min(mn,i * b);
break;
}
int cnt = i * b;
__int128 l = n,r = n;
while(l % m && l / m == r / m){
cnt += a;
l = l * k;
r = r * k + (k - 1);
}
mn = min(mn,cnt);
n = n / k;
}
cout << mn << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; cin >> t;
while(t --){
solve();
}
return 0;
}
G.匹配
i - j = ai - aj
显而易见可以变化为 ai - i =
aj - j
即 ai - i 值相同的可以匹配
那么就可以算出所有的 ai - i 然后sort后从最大的开始 两两相同的去匹配 只要匹配后的值 > 0 就可以算入答案 最后得到最大值
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 7;
int a[N];
pair<int,int> p[N];
int n;
void solve(){
cin >> n;
for(int i = 1;i <= n;i ++){
cin >> a[i];
int cnt = a[i] - i;
p[i] = {cnt,a[i]};
}
sort(p + 1,p + 1 + n);
int sum = 0;
for(int i = n;i >= 1;){
if(i - 1 < 1) break;
if(p[i].first != p[i - 1].first){
i --;
continue;
}
int cnt = p[i].second + p[i - 1].second;
if(cnt > 0) sum += cnt;
i -= 2;
}
cout << sum << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; cin >> t;
while(t --){
solve();
}
return 0;
}
I.三只骰子
直接三个for循环枚举看是否有符合题目要求的答案
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[6] = {1,4,2,3,5,6};
void solve(){
int A,B; cin >> A >> B;
for(int i = 0;i < 6;i ++){
for(int j = 0;j < 6;j ++){
for(int k = 0;k < 6;k ++){
int x = 0,y = 0;
if(i < 2) x += a[i];
else y += a[i];
if(k < 2) x += a[k];
else y += a[k];
if(j < 2) x += a[j];
else y += a[j];
if(x == A && y == B){
cout << "Yes" << endl;
return;
}
}
}
}
cout << "No" << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; t = 1;
while(t --){
solve();
}
return 0;
}
L.谜题:曲尺
直接以给出的(bi,bj)为对角线向其左上和右下套L,一直到无法向左上或者右下放L时,那么看他所处位置,判断是只往右上放还是往左下方即可
code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int x,y;
void solve(){
cin >> n >> x >> y;
int cnt = 1;
int x1,x2,y1,y2;
x1 = x2 = x;
y1 = y2 = y;
int x3,y3;
int nw = 1;
cout << "Yes" << endl << n - 1 << endl;
for(int i = 0;i < n - 1;i ++){
if(x1 > 1 && y1 > 1){
x1 --,y1 --;
cout << x1 << " " << y1 << " ";
cout << cnt << " " << cnt << endl;
} else if(x2 < n && y2 < n){
x2 ++,y2 ++;
cout << x2 << " " << y2 << " ";
cout << "-" << cnt << " -" << cnt << endl;
} else if(x1 == 1 && y2 == n){
cout << x2 + nw << " " << y1 - nw << " ";
cout << "-" << cnt << " " << cnt << endl;
nw ++;
} else if(y1 == 1 && x2 == n){
cout << x1 - nw << " " << y2 + nw << " ";
cout << cnt << " -" << cnt << endl;
nw ++;
}
cnt ++;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
int t; t = 1;
while(t --){
solve();
}
return 0;
}