0题,很尴尬。
Bronze Division:
1. Blocked Billboard
题意:给你两个不相交的长方形,和第三个长方形障碍物。问你前面两个长方形的可见面积是多少。
观察:因为前两个长方形不相交,分别计算每个长方形和障碍物之间的关系就好了
方法:注意如何处理不相交的情况

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <vector> 7 #include <unordered_map> 8 //#include <bits/stdc++.h> 9 #include <cassert> 10 #include <map> 11 #include <bitset> 12 using namespace std; 13 14 #define pb push_back 15 #define mp make_pair 16 typedef long long ll; 17 typedef unsigned long long ull; 18 typedef pair<int, int> ii; 19 20 21 int x[3][2], y[3][2]; 22 int solve(int id, int di) 23 { 24 int x1 = max(x[id][0], x[di][0]); 25 int x2 = min(x[id][1], x[di][1]); 26 int y1 = max(y[id][0], y[di][0]); 27 int y2 = min(y[id][1], y[di][1]); 28 return max(0, x2-x1)*max(0, y2-y1); 29 } 30 int main() 31 { 32 freopen("billboard.in", "r", stdin); 33 freopen("billboard.out", "w", stdout); 34 for (int i = 0; i < 3; ++i) 35 for (int j = 0; j < 2; ++j) 36 scanf("%d %d", &x[i][j], &y[i][j]); 37 int ans = 0; 38 for (int i = 0; i < 2; ++i) 39 ans += solve(i, i)-solve(i, 2); 40 printf("%d ", ans); 41 }
2. The Bovine Shuffle
题意:给你一个大小为n<=100的置换permutation,告诉你一个长度为n的array 被permutate 三次之后的结果,让你还原。
观察:因为只被permutate了三次,直接处理出permutation的inverse,模拟三遍就好了
方法:模拟

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <vector> 7 #include <unordered_map> 8 //#include <bits/stdc++.h> 9 #include <cassert> 10 #include <map> 11 #include <bitset> 12 using namespace std; 13 14 #define pb push_back 15 #define mp make_pair 16 typedef long long ll; 17 typedef unsigned long long ull; 18 typedef pair<int, int> ii; 19 20 const int maxn = 1e2+1; 21 int perm[maxn]; 22 int name[maxn]; 23 int a[maxn], b[maxn]; 24 int n; 25 int main() 26 { 27 freopen("shuffle.in", "r", stdin); 28 freopen("shuffle.out", "w", stdout); 29 30 scanf("%d", &n); 31 for (int i = 1; i <= n; ++i) 32 { 33 int x; 34 scanf("%d", &x); 35 perm[x] = i; 36 } 37 for (int i = 1; i <= n; ++i) 38 scanf("%d", name+i); 39 for (int i = 1; i <= n; ++i) 40 a[i] = i; 41 for (int t = 0; t < 3; ++t) 42 { 43 memcpy(b+1, a+1, n*sizeof(int)); 44 for (int i = 1; i <= n; ++i) 45 a[perm[i]] = b[i]; 46 47 } 48 for (int i = 1; i <= n; ++i) 49 printf("%d ", name[a[i]]); 50 }
但是如果permutate的次数很多该怎么办?我们想到,可以把permutation分成若干个cycles,这样不同的cycle之间是独立的,然后可以根据cycle上的位置关系,O(1)时间内判断任意一点t次permutation后(或者前)会到哪一位,这样就可以应付任意大小的permutation 次数了(本题题目中给定了三次)。注意,c++里 signed int modulo unsigned int, signed int是会被转成unsigned int的

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <vector> 7 #include <unordered_map> 8 //#include <bits/stdc++.h> 9 #include <cassert> 10 #include <map> 11 #include <bitset> 12 using namespace std; 13 14 #define pb push_back 15 #define mp make_pair 16 typedef long long ll; 17 typedef unsigned long long ull; 18 typedef pair<int, int> ii; 19 20 const int maxn = 1e2+1; 21 int perm[maxn]; 22 int name[maxn]; 23 int n; 24 vector<int> cycle[maxn]; 25 int id[maxn], pos[maxn]; 26 int tot=0; 27 int ans[maxn]; 28 int main() 29 { 30 freopen("shuffle.in", "r", stdin); 31 freopen("shuffle.out", "w", stdout); 32 scanf("%d", &n); 33 for (int i = 1; i <= n; ++i) 34 scanf("%d", perm+i); 35 for (int i = 1; i <= n; ++i) 36 scanf("%d", name+i); 37 //find cycle 38 for (int i = 1; i <= n; ++i) 39 if (id[i] == 0) 40 { 41 ++tot; 42 cycle[tot].clear(); 43 int cur = i; 44 while (!id[cur]) 45 { 46 id[cur] = tot; 47 pos[cur] = cycle[tot].size(); 48 cycle[tot].pb(cur); 49 cur = perm[cur]; 50 } 51 } 52 53 int perm_t = 3; 54 for (int i = 1; i <= n; ++i) 55 { 56 int prev = (pos[i]-perm_t)%(int)cycle[id[i]].size(); 57 58 if (prev < 0) 59 { 60 prev += (int)cycle[id[i]].size(); 61 } 62 ans[cycle[id[i]][prev]] = name[i]; 63 } 64 for (int i = 1; i <= n; ++i) 65 printf("%d ", ans[i]); 66 }
3. Milk Measurements
题意:有多(三)头奶牛,每个奶牛有一个产奶量(初始均为7,且始终不会超过1000)。然后给你不超过100组变化,形如(day, cow, diff),表示在第day<=1000天,奶牛cow的产奶量增加了diff。然后告诉你农场主会把产奶量最高的所有牛的名字写在墙上。最后让你求出农场主更改墙上内容的天数。
观察:数据比较小,暴力的做就好了。
方法:设计多个数据结构,按照天数一天天的算。

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 23 24 typedef pair<string, int> change; 25 const int maxd = 1e2+1; 26 const int maxn = 1e3+1; 27 vector<change> res[maxd]; 28 set<string> cnt[maxn]; 29 set<string> old; 30 map<string, int> output; 31 multiset<int> outputs; 32 #include <fstream> 33 int main() 34 { 35 ifstream cin("measurement.in"); 36 ofstream cout("measurement.out"); 37 ios::sync_with_stdio(false); 38 cin.tie(0); 39 int n; 40 cin >> n; 41 for (int i = 0; i < n; ++i) 42 { 43 int day; 44 string name; 45 int dif; 46 cin >> day >> name >> dif; 47 if (!output.count(name)) 48 { 49 output[name] = 7; 50 cnt[7].insert(name); 51 outputs.insert(7); 52 } 53 res[day].pb(mp(name, dif)); 54 } 55 int ans = 0; 56 old = cnt[7]; 57 for (int i = 1; i < maxd; ++i) 58 { 59 for (auto &e : res[i]) 60 { 61 outputs.erase(outputs.find(output[e.first])); 62 cnt[output[e.first]].erase(e.first); 63 outputs.insert(output[e.first]+=e.second); 64 cnt[output[e.first]].insert(e.first); 65 } 66 if (old != cnt[*outputs.rbegin()]) 67 { 68 ++ans; 69 old = cnt[*outputs.rbegin()]; 70 } 71 } 72 cout << ans << ' '; 73 }
做完silver version才发现自己这题读错了题,代码有问题。 因为只有三头奶牛,如果在input中,某一个奶牛的名字没有出现,而且出现的奶牛的产量低于7,那么上面代码可能会产生错误的答案。
修改后代码如下

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 23 24 typedef pair<string, int> change; 25 const int maxd = 1e2+1; 26 const int maxn = 1e3+1; 27 vector<change> res[maxd]; 28 set<string> cnt[maxn]; 29 set<string> old; 30 map<string, int> output; 31 multiset<int> outputs; 32 #include <fstream> 33 const string names[3] = {"Bessie","Elsie","Mildred"}; 34 int main() 35 { 36 ifstream cin("measurement.in"); 37 ofstream cout("measurement.out"); 38 ios::sync_with_stdio(false); 39 cin.tie(0); 40 int n; 41 cin >> n; 42 for (int i = 0; i < 3; ++i) 43 { 44 output[names[i]] = 7; 45 outputs.insert(7); 46 cnt[7].insert(names[i]); 47 } 48 for (int i = 0; i < n; ++i) 49 { 50 int day; 51 string name; 52 int dif; 53 cin >> day >> name >> dif; 54 res[day].pb(mp(name, dif)); 55 } 56 int ans = 0; 57 old = cnt[7]; 58 for (int i = 1; i < maxd; ++i) 59 { 60 for (auto &e : res[i]) 61 { 62 outputs.erase(outputs.find(output[e.first])); 63 cnt[output[e.first]].erase(e.first); 64 outputs.insert(output[e.first]+=e.second); 65 cnt[output[e.first]].insert(e.first); 66 } 67 if (old != cnt[*outputs.rbegin()]) 68 { 69 ++ans; 70 old = cnt[*outputs.rbegin()]; 71 } 72 } 73 cout << ans << ' '; 74 }
Silver Division:
1. My Cow Ate My Homework
题意:你有n<=1e5个homework,每个homework有一个得分a[i] <= 1e4。对于任意的k (1<=k<=n-2), 你的牛可以把k个作业吃掉。老师计算你的作业总得分时,把剩下的作业,除去最低分,然后去平均数。下面让你输出所有的能使你作业总得分最高的k。
观察:预处理出后缀和,还有每个后缀中最小的元素,就可以O(1)查询每个k所对应的最终得分。
方法:预处理后缀和,同时预处理出每个后缀中最小的元素,线性跑两遍,第一遍确定最大得分,第二遍遇到最大得分就输出答案。

#include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <iostream> #include <iomanip> #include <vector> #include <unordered_map> //#include <bits/stdc++.h> #include <cassert> #include <set> #include <map> #include <bitset> using namespace std; #define pb push_back #define mp make_pair typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> ii; const int maxn = 1e5+1; int sum[maxn], mini[maxn], a[maxn], n; int main() { freopen("homework.in", "r", stdin); freopen("homework.out", "w", stdout); scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", a+i); sum[n] = mini[n] = a[n]; for (int i = n-1; i >= 1; --i) { sum[i] = a[i] + sum[i+1]; mini[i] = min(a[i], mini[i+1]); } int ans = -1, pos = 1; for (int i = 2; i <= n-1; ++i) { ll dif = 1ll*pos*(sum[i]-mini[i])-1ll*(n-i)*ans; if (dif > 0) ans = sum[i]-mini[i], pos = n-i; } for (int i = 2; i <= n-1; ++i) { ll dif = 1ll*pos*(sum[i]-mini[i])-1ll*(n-i)*ans; if (dif == 0) printf("%d ", i-1); } }
2. Milk Measurements
Bronze Division 的加强版。读完这道题之后才发现bronze version的题读错了。
题意:有无限头奶牛,每个奶牛有一个产奶量(初始均为g,且始终不会超过1e9)。然后给你不超过100000组变化,形如(day, cow, diff),表示在第day<=1e6天,奶牛cow<=1e9的产奶量增加了diff。然后告诉你农场主会把产奶量最高的所有牛的名字写在墙上。最后让你求出农场主更改墙上内容的天数。
观察:和bronze version做法一样,不过因为产奶量变大了,需要离散化一下。同时注意有无限头奶牛,也就是总会有奶牛的产奶量是g。
方法:设计多个数据结构,按照天数一天天的算。初始的时候插入一个编号为-1的pseudo cow,保证无论什么时候都会有产量为g的奶牛。

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 23 24 typedef pair<int, int> change; 25 const int maxd = 1e6+1; 26 27 vector<change> res[maxd]; 28 map<int, set<int> > cnt; 29 set<int> old; 30 map<int, int> output; 31 multiset<int> outputs; 32 #include <fstream> 33 int main() 34 { 35 ifstream cin("measurement.in"); 36 ofstream cout("measurement.out"); 37 ios::sync_with_stdio(false); 38 cin.tie(0); 39 int n; 40 int g; 41 cin >> n >> g; 42 for (int i = 0; i < n; ++i) 43 { 44 int day; 45 int name; 46 int dif; 47 cin >> day >> name >> dif; 48 if (!output.count(name)) 49 { 50 output[name] = g; 51 cnt[g].insert(name); 52 outputs.insert(g); 53 } 54 res[day].pb(mp(name, dif)); 55 } 56 int ans = 0; 57 output[-1] = g; 58 cnt[g].insert(-1); 59 outputs.insert(g); 60 old = cnt[g]; 61 for (int i = 1; i < maxd; ++i) 62 { 63 for (auto &e : res[i]) 64 { 65 outputs.erase(outputs.find(output[e.first])); 66 cnt[output[e.first]].erase(e.first); 67 outputs.insert(output[e.first]+=e.second); 68 cnt[output[e.first]].insert(e.first); 69 } 70 if (old != cnt[*outputs.rbegin()]) 71 { 72 ++ans; 73 old = cnt[*outputs.rbegin()]; 74 } 75 } 76 cout << ans << ' '; 77 }
3. The Bovine Shuffle
题意:有n头奶牛,初始时第i只奶牛站在第i位。一轮之后,站在i的所有奶牛会走到a[i]。你会发现,有些位置可能没有奶牛,有些位置一直都有奶牛,问你有多少个位置一直都会有奶牛。
观察:其实是求a^n的image大小。可以把位置看成点,i -> a[i] 看成边,那么每个点的出度都为1,所以,从每个点出发,经过若干步都会走到一个环,而且每个联通分量只有一个环。环上的元素,始终有牛。
方法:dfs一下,记录dfs的深度,如果同一个点在同一轮dfs被visit了两次,那么就找到环了。环长为两次visit时间(深度)之差。注意如何避免同一联通分量的环被多次计算。

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 const int maxn = 1e5+1; 23 int n, a[maxn]; 24 int t[maxn]; 25 int rounds[maxn]; 26 int ans = 0; 27 void dfs(int cur, int time, int r) 28 { 29 if (t[cur]) 30 { 31 if (rounds[cur] == r) 32 { 33 ans += time-t[cur]; 34 } 35 } 36 else 37 { 38 rounds[cur] = r; 39 t[cur] = time; 40 dfs(a[cur], time+1, r); 41 } 42 } 43 int main() 44 { 45 freopen("shuffle.in", "r", stdin); 46 freopen("shuffle.out", "w", stdout); 47 scanf("%d", &n); 48 for (int i = 1; i <= n; ++i) 49 scanf("%d", a+i); 50 for (int i = 1; i <= n; ++i) 51 dfs(i, 1, i); 52 printf("%d ", ans); 53 }
也可以bfs,把入度为0的点依次删掉,剩下的点就是环伤的点。

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 const int maxn = 1e5+1; 23 int n, a[maxn], in[maxn]={0}; 24 25 int main() 26 { 27 freopen("shuffle.in", "r", stdin); 28 freopen("shuffle.out", "w", stdout); 29 scanf("%d", &n); 30 for (int i = 1; i <= n; ++i) 31 { 32 scanf("%d", a+i); 33 ++in[a[i]]; 34 } 35 queue<int> q; 36 for (int i = 1; i <= n; ++i) 37 if (in[i] == 0) 38 q.push(i); 39 while (!q.empty()) 40 { 41 int cur = q.front(); 42 q.pop(); 43 --in[a[cur]]; 44 if (in[a[cur]] == 0) 45 q.push(a[cur]); 46 } 47 int ans = 0; 48 for (int i = 1; i <= n; ++i) 49 if (in[i] != 0) 50 ++ans; 51 printf("%d ", ans); 52 }
Gold Division:
1. A Pie for a Pie
题意:两只牛,牛A和牛B,他们对水果派的品味不同,每个人都有n<=1e5个派,每个派都有两种得分a[i], b[i],其中a[i]是牛A对该派的评分,b[i]是牛B的评分, 0 <= a[i], b[i] <= 1e9。两只牛开始礼尚往来,从牛A开始,它选一个pie给牛B,设这个pie的评分是(a[i], b[i])。此时牛B为了不失礼节(不太小气,也不要太谄媚)要选出一个B评分在[b[i], b[i]+d]范围内的pie(a[j], b[j]),给A。同理,A又要选出一个A评分在[a[j], a[j]+d]范围内的pie给B,如此往复。每个pie都只能传递一次。如果A收到了一个A评分为0的pie,或者B收到了一个B评分为0的pie,那么礼尚往来就愉快的结束了。否则,就不愉快结束(即一个人无法选出合法的pie给对方时)。下面让你输出,对于A的每一个pie,如果第一轮A把这个pie交给B,礼尚往来最少可以几轮愉快结束?如果无法愉快结束,就输出-1。
观察:根据样例可以大致推算出做法,先找到可以是游戏结束的pie,即A中B评分为0的pie和B中A评分为0的,使用这些pie后,到游戏结束至少需要一轮,我们在找这些pie的前驱,一轮轮的找,其实就是一个反向bfs的过程。选点时可以用一个set来快速找出。
方法:

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 23 const int maxn = 1e5+1; 24 25 struct Point 26 { 27 int x[2], t; 28 inline void read() 29 { 30 scanf("%d %d", &x[0], &x[1]); 31 } 32 } p[2][maxn]; 33 int n, d; 34 set<ii> res[2]; 35 int ans[2][maxn]; 36 int main() 37 { 38 freopen("piepie.in", "r", stdin); 39 freopen("piepie.out", "w", stdout); 40 scanf("%d", &n); 41 scanf("%d", &d); 42 for (int t = 0; t < 2; ++t) 43 for (int i = 0; i < n; ++i) 44 p[t][i].read(), res[t].insert(mp(p[t][i].x[t^1], i)); 45 memset(ans, -1, sizeof(ans)); 46 queue<ii> q; 47 for (int i = 0; i < 2; ++i) 48 { 49 while (!res[i].empty() && res[i].begin()->first == 0) 50 { 51 ans[i][res[i].begin()->second] = 1; 52 q.push(mp(i, res[i].begin()->second)); 53 res[i].erase(res[i].begin()); 54 } 55 } 56 for (int tar = 2; !q.empty(); ++tar) 57 { 58 int sz = q.size(); 59 for (int t = 0; t < sz; ++t) 60 { 61 ii cur = q.front(); 62 // cerr << "cur = " << cur.first << " " << cur.second << endl; 63 q.pop(); 64 int a = cur.first^1; 65 int b = p[cur.first][cur.second].x[cur.first]; 66 // cerr << "look for " << a << " " << b << endl; 67 for (;;) 68 { 69 auto it = res[a].lower_bound(mp(b+1, 0)); 70 if (it == res[a].begin()) 71 break; 72 --it; 73 if (it->first < b-d) 74 break; 75 // cerr << "push " << a << " " << it->second << endl; 76 ans[a][it->second] = tar; 77 q.push(mp(a, it->second)); 78 res[a].erase(it); 79 } 80 } 81 } 82 for (int i = 0; i < n; ++i) 83 printf("%d ", ans[0][i]); 84 }
2. Barn Painting
题意:给你一颗大小为n<=1e5的树,三种颜色,每个点涂一种颜色,相邻点不能同色。下面告诉你一些点已经被涂色,并且告诉你是哪一种颜色,问你涂完整棵树有多少种方法?mod 1e9+7。
观察:假如没有已涂色的限制条件,那么就可以从任意一个点出发,向周围扩散。但是有限制,所以想到可以树上dp一下。
方法:无根树转有根树,dp[i][c]表示当i结点涂c(1<=c<=3)色时,i结点所在子树有少种涂色方法,dp[i][0]表示i所在子树一共有多少种涂色方式。答案是dp[root][0]。

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 23 const int maxn = 1e5+1; 24 ll d[maxn][4]; 25 const int mod = 1e9+7; 26 vector<int> g[maxn]; 27 void dfs(int cur, int pa) 28 { 29 if (d[cur][0] == -1) 30 { 31 memset(d[cur], 0, sizeof(d[cur])); 32 for (int i = 1; i <= 3; ++i) 33 d[cur][i] = 1; 34 } 35 for (auto nxt : g[cur]) 36 { 37 if (nxt == pa) 38 continue; 39 dfs(nxt, cur); 40 for (int i = 1; i <= 3; ++i) 41 d[cur][i] = (d[cur][i]*(d[nxt][0]-d[nxt][i]))%mod; 42 } 43 for (int i = 1; i <= 3; ++i) 44 d[cur][0] = (d[cur][0]+d[cur][i])%mod; 45 } 46 int main() 47 { 48 freopen("barnpainting.in", "r", stdin); 49 freopen("barnpainting.out", "w", stdout); 50 memset(d, -1, sizeof(d)); 51 int n, k; 52 scanf("%d %d", &n, &k); 53 for (int i = 1; i <= n-1; ++i) 54 { 55 int u, v; 56 scanf("%d %d", &u, &v); 57 g[u].pb(v); 58 g[v].pb(u); 59 } 60 for (int i = 1; i <= k; ++i) 61 { 62 int a, b; 63 scanf("%d %d", &a, &b); 64 memset(d[a], 0, sizeof(d[a])); 65 d[a][b] = 1; 66 } 67 dfs(1, 0); 68 if (d[1][0] < 0) 69 d[1][0] += mod; 70 printf("%lld ", d[1][0]); 71 }
3. Haybale Feast
题意:给长度为n<=1e5的两个序列f[], s[] <= 1e9和一个long long M。如果[1, n] 的一个子区间[a, b]满足 f[a]+f[a+1]+..+f[b] >= M, 我们就称[a, b]合法,一个合法区间[a, b]的值为max(s[a], s[a+1], ..., s[b])。让你求出可能的合法区间最小值为多少。
观察:区间最值大值随着区间的长度增加肯定是非递减的,所以对于一个左端点a,我们只需考虑使[a, b]合法的最小的b。这个通过滑动窗口就可以做到,同时利用单调队列维护最值。
方法:

1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 #include <iostream> 6 #include <iomanip> 7 #include <vector> 8 #include <unordered_map> 9 //#include <bits/stdc++.h> 10 #include <cassert> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 using namespace std; 15 16 #define pb push_back 17 #define mp make_pair 18 typedef long long ll; 19 typedef unsigned long long ull; 20 typedef pair<int, int> ii; 21 22 const int maxn = 1e5+1; 23 int n; 24 ll f[maxn], s[maxn], m; 25 int main() 26 { 27 freopen("hayfeast.in", "r", stdin); 28 freopen("hayfeast.out", "w", stdout); 29 scanf("%d %lld", &n, &m); 30 for (int i = 1; i <= n; ++i) 31 scanf("%lld %lld", f+i, s+i); 32 ll sum = 0; 33 deque<int> q; 34 int nxt = 1; 35 ll ans = 1e18; 36 for (int i = 1; i <= n; ++i) 37 { 38 while (nxt <= n && sum < m) 39 { 40 sum += f[nxt]; 41 while (!q.empty() && s[q.back()] <= s[nxt]) 42 q.pop_back(); 43 q.push_back(nxt); 44 ++nxt; 45 } 46 if (sum < m) 47 break; 48 if (s[q.front()] < ans) 49 ans = s[q.front()]; 50 if (q.front() == i) 51 q.pop_front(); 52 sum -= f[i]; 53 } 54 printf("%lld ", ans); 55 }
做完前三个division感觉,bronze division是最难的。。。接下来的platinum division real time的时候一道题都没做出来。。现在重新读一下题目,看看有没有什么思路,目测会是搬运题解。
Platinum Division: