zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", 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 << '
    ';
    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 << '
    ';
    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
    ", 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 << '
    ';
    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
    ", 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
    ", 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
    ", 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
    ", 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
    ", ans);
    55 }
    View Code

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

    Platinum Division:

  • 相关阅读:
    系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式[转]
    EF RepositoryBase 参考示例【转】
    Entity Framework 杂碎
    Oracle.ManagedDataAccessDTC.dll 使用
    c# http请求,获取非200时的响应体
    c# windows service(服务)
    git log
    解决冲突
    clone命令
    remote指令添加远程数据库
  • 原文地址:https://www.cnblogs.com/skyette/p/8093136.html
Copyright © 2011-2022 走看看