杭电多校第五场个人补题 3 10 12
12
题意
有m条队n个人,每个人在 a i a_i ai时间来,付款要付 s i s_i si时间,问最后一个人付完款最早要多长时间
思路
纯模拟,赛时先想的是拿两个优先队列写,一个储存队伍长度,一个储存m个队伍的时间(后来听说也可以用二分线段树写),但是发现需要手写一个优先队列来实现查找,最后队友优化了一下,拿了一个set存每个队伍的长度模拟一下就过了。
代码
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 4e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int cnt[1000010];
int tti[1000010];
void solve(){
int n, m;
cin >> n >> m;
int mi = 0;
int nt = 1;
for(int i = 1;i <= m;i++){
cnt[i] = 0;
tti[i] = 0;
}
vector<pair<int,int>> v(n);
set<pair<int,int>> st;
for(int i = 0;i < n;i++){
cin >> v[i].first >> v[i].second;
}
for(int i = 1;i <= m;i++){
st.insert({0, i});
}
sort(v.begin(), v.end());
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
for(int i = 0;i < n;i++){
int x, y;
x = v[i].first;
y = v[i].second;
while(q.size() && q.top().first < x){
int u = q.top().second;
st.erase({cnt[u], u});
cnt[u]--;
st.insert({cnt[u], u});
q.pop();
}
pair<int,int> ki = *st.begin();
st.erase({cnt[ki.second], ki.second});
cnt[ki.second]++;
st.insert({cnt[ki.second], ki.second});
nt = ki.second;
q.push({max(x, tti[nt]) + y, nt});
tti[nt] = max(x, tti[nt]) + y;
//cout << nt << ' ' << tti[nt] << "\n";
}
cout << *max_element(tti + 1, tti + 1 + m) << "\n";
}
signed main(){
int T;
cin >> T;
while(T--){
solve();
}
return 0;
}
10
题意
双方各n个骰子,现在已知所有骰子点数,如果没有人猜点数1的个数,点数为1的骰子可以当作任意点数,每一边中有相同点数的骰子则该点数骰子个数加一,一边n个骰子点数都不相同则视为这一边任意点数都不存在(此规则优先级最高,问是先手赢还是后手赢。
思路
这题,感觉说的不是很清楚,没人猜点数为1的骰子的话不是样例先手输赢都说得过去吗???后来队友猜了个结论是只要有骰子点数就先手赢,结果我用c++17的标准ce了三发,最后过了,属实不懂。。。
代码
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 4e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
map<int,int>mp1,mp2;
bool cmp(PII a,PII b) {
if(a.first!=b.first) return a.first<b.first;
return a.second>=b.second;
}
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++) {
int x;
cin>>x;
mp1[x]++;
}
for(int i=1;i<=n;i++) {
int x;
cin>>x;
mp2[x]++;
}
if((int)mp1.size()==n) {
mp1.clear();
}
if((int)mp2.size()==n) {
mp2.clear();
}
map<int,int>mp;
if(mp1.size()==1) {
mp[mp1.begin()->first]++;
}
if(mp2.size()==1) {
mp[mp1.begin()->first]++;
}
for(auto it:mp1) mp[it.first]+=it.second;
for(auto it:mp2) mp[it.first]+=it.second;
if(mp.size()==0) {
cout<<"Just a game of chance.\n";
}
else cout<<"Win!\n";
// vector<PII>v;
// for(auto [i,j]:mp) {
// v.push_back({j,i});
// }
// sort(v.begin(),v.end(),cmp);
mp1.clear();
mp2.clear();
}
signed main(){
IOS;
int T=1;
cin >> T;
while(T--){
solve();
}
}
3
题意
给一棵树,现在相差深度为k的两层之间可以互相跳跃,权值为p,问从s到t的最短路是多少。
思路
比赛的时候想的是n方建图然后硬跑最短路,结果不停的t,改成邻接表也不行,后来看题解才发现跳跃的操作可以每层开两个虚拟的点分别都做单向边(一个点双向边会可以在同层之间跳不合法。。。),属实是见识了。
代码
#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 4e6 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 5;
typedef pair<int, int> PII;
int h[maxn << 2], e[maxn << 3], ne[maxn << 3], idx, w[maxn << 3];
void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}//邻接表存图
long long dis[maxn << 2];
bool vis[maxn << 2];
int n, k, p, st, ed, mxdp;
int deep[maxn << 2];
void dfs(int u, int f, int d) {
deep[u] = d;
mxdp = max(mxdp, d);
for (int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if (v != f) {
dfs(v, u, d + 1);
}
}
}
void dijkstra(int k1) {
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> q;
dis[k1] = 0;
q.push({0, k1});
while (q.size()) {
auto t = q.top();
q.pop();
int u = t.second;
int d = t.first;
if (vis[u])continue;
vis[u] = 1;
for (int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if (dis[v] > dis[u] + w[i]) {
dis[v] = dis[u] + w[i];
q.push({dis[v], v});
// cout << u << ' ' << v << ' ' << dis[v] << endl;
}
}
}
}
void solve() {
scanf("%d", &n);
mxdp = 0;
memset(h, -1, sizeof h);
memset(e, 0, sizeof e);
memset(w, 0, sizeof w);
memset(ne, 0, sizeof ne);
idx = 0;
for (int i = 0; i < n - 1; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(1, 0, 0);
scanf("%d%d", &k, &p);
for (int i = 1; i <= n; i++) {
if (deep[i] != 0)
add(n + 2 * deep[i] - 1, i, p);
if (deep[i] != mxdp)
add(n + 2 * (deep[i] + 1), i, p);
if (deep[i] + k <= mxdp)
add(i, n + 2 * (deep[i] + k) - 1, 0);
if (deep[i] - k >= 0)
add(i, n + 2 * (deep[i] - k + 1), 0);
}
scanf("%d%d", &st, &ed);
// for (int i = 1; i <= 10000; i++) {
// for (int j = h[i]; j != -1; j = ne[j]) {
// int v = e[j];
// cout << i << " -> " << v << ' ' << w[j] << endl;
// }
// }
dijkstra(st);
printf("%lld\n", dis[ed]);
}
signed main() {
//IOS;
int T;
scanf("%d", &T);
while (T--) {
solve();
}
}