CCPC-Wannafly Winter Camp Day4 (Div2, onsite)

 

 

 

Replay


 

 

Dup4:

  • 两轮怎么退火啊?
  • 简单树形dp都不会了,送了那么多罚时
  • 简单题都不想清楚就乱写了,喵喵喵?

 X:

  • 欧拉怎么回路啊, 不会啊。
  • 还是有没有手误?未思考清楚或者未检查就提交, 导致自己白送罚时。

 

 

 

 

 

 

 

 

 

A:夺宝奇兵

Solved.

考虑$所有i >= 2 需要跟i - 1 连两条边 只有两种可能 取最小的一种$

$注意n的两个点要连一条边$

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int maxn = 1e5 + 10;
 8 
 9 struct node{
10     int x1, x2, y1, y2;
11 }arr[maxn];
12 
13 ll calc(int i,int j)
14 {
15     ll ans1 = abs(arr[i].x1 - arr[j].x1) + abs(arr[i].y1 - arr[j].y1) + abs(arr[i].x2 - arr[j].x2) + abs(arr[i].y2 - arr[j].y2);
16     ll ans2 = abs(arr[i].x1 - arr[j].x2) + abs(arr[i].y1 - arr[j].y2) + abs(arr[i].x2 - arr[j].x1) + abs(arr[i].y2 - arr[j].y1);
17     return min(ans1, ans2);
18 }
19 
20 int n , m;
21 
22 int main()
23 {
24     while(~scanf("%d %d", &n, &m))
25     {
26         for(int i = 1; i <= n; ++i) scanf("%d %d %d %d", &arr[i].x1, &arr[i].y1, &arr[i].x2, &arr[i].y2);
27         ll ans = 0;
28         for(int i = 2; i <= n; ++i) ans += calc(i, i - 1);
29         ans += abs(arr[n].x1 - arr[n].x2) + abs(arr[n].y1 - arr[n].y2);
30         printf("%lld\n", ans);
31     }
32     return 0;
33 }
View Code

 

C:最小边覆盖

Solved.

考虑$No的情况$

  • 存在一个点的度数为0(没有被覆盖)
  • 存在一条边所连接的两个点其度数 >= 2 即这条边去掉还是个最小边覆盖
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 300010
 5 #define pii pair <int, int>
 6 int n, m;
 7 pii G[N];
 8 int d[N];
 9 
10 bool f()
11 {
12     for (int i = 1; i <= n; ++i) if (!d[i]) return false;
13     for (int i = 1; i <= m; ++i)
14     {
15         int u = G[i].first, v = G[i].second;
16         if (d[u] >= 2 && d[v] >= 2)
17             return false;
18     }
19     return true;
20 }
21 
22 int main()
23 {
24     while (scanf("%d%d", &n, &m) != EOF)
25     {
26         memset(d, 0, sizeof d);
27         for (int i = 1, u, v; i <= m; ++i)
28         {
29             scanf("%d%d", &u, &v);
30             ++d[u], ++d[v];
31             G[i] = pii(u, v);
32         }
33         puts(f() ? "Yes" : "No");
34     }
35     return 0;
36 }
View Code

 

F:小小马

Solved.

因为不同颜色出现次数相同, 所以步数一定是奇数。

暴力跑出大数据的状态, 发现颜色相同就输出No, 否则输出Yes。

小数据暴力跑即可

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e6 + 10;
 6 
 7 struct node{
 8     int x, y;
 9     int step;
10     node(){}
11     node(int x, int y, int step): x(x), y(y), step(step){}
12 };
13 
14 int n, m;
15 int sx, sy, ex, ey;
16 int vis[11][maxn][2];
17 int dir[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};
18 
19 int judge(int x, int y,int step)
20 {
21     if(x < 1 || x > n || y < 1 || y > m || vis[x][y][step % 2]) return false;
22     else return true;    
23 }
24 
25 void BFS()
26 {
27     memset(vis, 0, sizeof vis);
28     queue<node>q;
29     q.push(node(sx, sy, 0));
30     while(!q.empty())
31     {
32         node st = q.front();
33         q.pop();
34         node now = st;
35         now.step++;
36         for(int i = 0; i < 8; ++i)
37         {
38             now.x = st.x + dir[i][0];
39             now.y = st.y + dir[i][1];
40             if(judge(now.x, now.y, now.step))
41             {
42                 vis[now.x][now.y][now.step % 2] = 1;
43                 q.push(now);
44             }
45         }
46     }
47 }
48 
49 int main()
50 {
51     while(~scanf("%d %d", &n, &m))
52     {
53         scanf("%d %d", &sx, &sy);
54         scanf("%d %d", &ex, &ey);
55         if(n < 10 || m < 10)
56         {
57             if(n > m) 
58             {
59                 swap(n, m);
60                 swap(sx, sy);
61                 swap(ex, ey);
62             }
63             BFS();
64             if(vis[ex][ey][1]) puts("Yes");
65             else puts("No");
66         }
67         else
68         {
69             int ans1 = (sx + sy) % 2;
70             int ans2 = (ex + ey) % 2;
71             if(ans1 != ans2) puts("Yes");
72             else puts("No");
73         }        
74     }
75     return 0;
76 }
View Code

 

 

G:置置置换

Solved.

$在已知1-n的方案数, 枚举n+1出现的位置$

$当枚举到位置x的时候, 选出x-1个数放在前x个, 然后计算方案数 统计即可$

$2 \cdot ans_{n + 1} = \sum\limits_{i = 0}^{n} C_n^i \cdot ans_i \cdot ans_{n - i}$

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const ll MOD = (ll)1e9 + 7;
 8 const int maxn = 1e3 + 10;
 9 
10 int n;
11 ll fac[maxn];
12 ll inv[maxn];
13 ll invfac[maxn];
14 
15 ll ans[maxn];
16 
17 void Init()
18 {
19     fac[1] = 1, inv[1] = 1, invfac[1] = 1;
20     for(int i = 2; i < maxn; ++i)
21     {
22         fac[i] = fac[i - 1] * i % MOD;
23         inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
24         invfac[i] = invfac[i - 1] * inv[i]  % MOD;
25     }
26 }
27 
28 ll calc(int n, int m)
29 {
30     if(n == m || m == 0) return 1ll;
31     return fac[n] * invfac[m] % MOD * invfac[n - m] % MOD;
32 }
33 
34 
35 int main()
36 {
37     Init();
38     ans[0] = ans[1] = 1;
39     for(int i = 1; i + 1 < maxn; ++i)
40     {
41         for(int j = 0; j <= i; ++j)
42         {
43             ans[i + 1] = (ans[i + 1] + calc(i, j) * ans[j] % MOD * ans[i - j] % MOD) % MOD;
44         }
45         ans[i + 1] = (ans[i + 1] * inv[2]) % MOD;
46     }
47     while (scanf("%d", &n) != EOF)
48     {
49         printf("%lld\n", ans[n]);
50     }
51     return 0;
52 }
View Code



I:咆咆咆哮

Solved.

考虑如果选择$a_i的个数固定为x,那么对于所有选取b_i的卡牌来说它的贡献是固定的$

枚举$x, 再贪心选取即可$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 1010
 6 int n, a[N], b[N];
 7 
 8 ll f(int x)
 9 {
10     priority_queue <ll> pq;
11     ll res = 0;
12     for (int i = 1; i <= n; ++i) 
13     {
14         res += a[i];
15         pq.push(1ll * b[i] * x - a[i]);
16     }    
17     for (int i = 1; i <= n - x; ++i) 
18     {
19         res += pq.top();
20         pq.pop();
21     }
22     return res;
23 }
24 
25 int main()
26 {
27     while (scanf("%d", &n) != EOF)
28     {
29         for (int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
30         ll res = 0;
31         for (int i = 1; i <= n; ++i)
32             res = max(res, f(i));
33         printf("%lld\n", res);
34     }
35     return 0;
36 }
View Code

 

Div1:

三分

好像满足凸性? 我不会证啊。..

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 int n, a[N], b[N];
 7 
 8 ll check(int x)
 9 {
10     ll res = 0;
11     priority_queue <ll> pq;
12     for (int i = 1; i <= n; ++i)
13     {
14         res = res + a[i];
15         pq.push(1ll * b[i] * x - a[i]);
16     }
17     for (int i = n - x; !pq.empty() && i; --i)
18     {
19         res += pq.top(); pq.pop();
20     }
21     return res;
22 }
23 
24 int main()
25 {
26     while (scanf("%d", &n) != EOF)
27     {
28         for (int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
29         int l = 0, r = n; ll res = 0;
30         while (r - l >= 0)
31         {
32             int midl = (l + r) >> 1;
33             int midr = (midl + r) >> 1;
34             ll tmpl = check(midl); 
35             ll tmpr = check(midr);
36             if (tmpl <= tmpr)
37             {
38                 res = max(res, tmpr);
39                 l = midl + 1;
40             }
41             else
42             {
43                 res = max(res, tmpl);
44                 r = midr - 1;
45             }
46         }
47         printf("%lld\n", res);
48     }
49     return 0;
50 }
View Code

 

K:两条路径

Solved.

考虑$x作为交它的权值要被算上$

在考虑两条路径可以选取端点,端点的选择在其儿子对应的子树中选取一个点且仅能选取一个

树形DP即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 #define INFLL 0x3f3f3f3f3f3f3f3f
 7 int n, q;
 8 ll val[N];
 9 vector <int> G[N];
10 ll Bit[35], f[N];
11 
12 void DFS(int u, int fa)
13 {
14     f[u] = -INFLL;
15     for (auto v : G[u]) if (v != fa)
16     {
17         DFS(v, u);
18         f[u] = max(f[u], f[v]);
19     }    
20     f[u] = max(f[u], 0ll);
21     f[u] += val[u];
22 }
23 
24 void out(ll x)
25 {
26     if (x < 0) putchar('-'), x = -x;
27     string res = "";
28     while (x)
29     {
30         res += (x % 2 + '0');  
31         x /= 2;
32     }
33     reverse(res.begin(), res.end());
34     cout << res << "\n";
35 }
36 
37 int main()
38 {
39     Bit[0] = 1;
40     for (int i = 1; i <= 30; ++i) Bit[i] = Bit[i - 1] << 1;
41     while (scanf("%d", &n) != EOF)
42     {
43         for (int i = 1; i <= n; ++i) G[i].clear();
44         for (int i = 1, x; i <= n; ++i) 
45         {
46             scanf("%d", &x);
47             if (!x) 
48             {
49                 val[i] = 0;
50                 continue;
51             }
52             int vis = 1;
53             if (x < 0)
54             {
55                 x = -x;
56                 vis = -1;
57             }
58             --x;
59             val[i] = Bit[x] * vis;
60         }
61         for (int i = 1, u, v; i < n; ++i) 
62         {
63             scanf("%d%d", &u, &v);
64             G[u].push_back(v);
65             G[v].push_back(u); 
66         }
67         int x;
68         scanf("%d", &q);
69         while (q--)
70         {
71             scanf("%d", &x);
72             priority_queue <ll> pq;
73             for (auto v : G[x]) 
74             {
75                 DFS(v, x);
76                 pq.push(f[v]);
77             }
78             ll res = val[x];
79             for (int i = 1; i <= 4 && !pq.empty() && pq.top() > 0; ++i)
80             {
81                 res += pq.top(); pq.pop(); 
82             }
83             //cout << res << endl;
84             out(res);
85         }
86     }
87     return 0;
88 }
View Code

 

posted @ 2019-01-23 19:52  Dup4  阅读(289)  评论(0编辑  收藏  举报