USACO 2017 December Contest

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\n", ans);
41 }
View Code

 

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\n", name[a[i]]);
50 }
View Code

但是如果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\n", ans[i]);
66 }
View Code

 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 << '\n';
73 }
View Code

做完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 << '\n';
74 }
View Code

 

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\n", i-1);
    }

}
View Code

 

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 << '\n';
77 }
View Code

 

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\n", ans);
53 }
View Code

也可以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\n", ans);
52 }
View Code

 

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\n", ans[0][i]);
84 }
View Code

 

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\n", d[1][0]);
71 }
View Code

 

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\n", ans);
55 }
View Code

 

做完前三个division感觉,bronze division是最难的。。。接下来的platinum division real time的时候一道题都没做出来。。现在重新读一下题目,看看有没有什么思路,目测会是搬运题解。

Platinum Division:

转载于:https://www.cnblogs.com/skyette/p/8093136.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值