牛客国庆集训派对Day1 Solution

A    Tobaku Mokushiroku Kaiji

水。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int a[3], b[3];
 5 
 6 void Run()
 7 {
 8     while (scanf("%d", a) != EOF)
 9     {
10         for (int i = 1; i < 3; ++i) scanf("%d", a + i);
11         for (int i = 0; i < 3; ++i) scanf("%d", b + i); 
12         printf("%d\n", min(a[0], b[1]) + min(a[1], b[2]) + min(a[2], b[0]));  
13     }
14 }
15 
16 int main()
17 {
18     #ifdef LOCAL
19         freopen("Test.in", "r", stdin);
20     #endif    
21         
22     Run();
23     return 0;
24 }
View Code

 

B    Attack on Titan

留坑。

 

C    Utawarerumono

思路:好像暴力就能过。

 1 #include <bits/stdc++.h>
 2 using namespace std; 
 3 using ll = long long;
 4 
 5 ll a, b, c, p1, p2, q1, q2;
 6 
 7 int main() 
 8 {
 9     while (scanf("%lld%lld%lld", &a, &b, &c) != EOF) 
10     {
11         scanf("%lld%lld", &p1, &p2);
12         scanf("%lld%lld", &q1, &q2);
13         ll res = 0x3f3f3f3f3f3f3f3f;
14         for (ll x = -100000; x <= 100000; ++x)
15         {
16             if ((c - a * x) % b) continue;
17             ll y = (c - a * x) / b;
18             res = min(res, p2 * x * x + p1 * x + q2 * y * y + q1 * y);
19         }
20         if (res == 0x3f3f3f3f3f3f3f3f)
21         {
22             puts("Kuon");
23             continue;
24         }
25         printf("%lld\n", res);
26     }
27     return 0;
28 }
View Code

 

 

D    Love Live!

思路:将边按权值从小到大排序,一条一条往里加,每加入一条边要合并两个联通块,用并查集维护,然后开n棵trie树维护异或最大,简单路径上的异或和可以理解为两个点到根节点的前缀异或再异或,合并的时候启发式合并,查询的时候一定要经过那条边,那就是用一个联通块里的元素查找在另一个联通块对应的trie树里面查找,启发式查找

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 100010
  5 
  6 struct Edge
  7 {
  8     int u, v, nx, w;
  9     Edge() {}
 10     Edge(int u, int v, int nx, int w) : u(u), v(v), nx(nx), w(w) {}
 11     Edge(int u, int v, int w) : u(u), v(v), w(w) {} 
 12     bool operator < (const Edge &r) const
 13     {
 14         return w < r.w;  
 15     }
 16 }edge[N << 1], G[N];
 17 
 18 int n;
 19 int head[N], pos;
 20 int prefix[N], fa[N], sz[N];
 21 vector <int> v[N];
 22 
 23 void addedge(int u, int v, int w)
 24 {
 25     edge[++pos] = Edge(u, v, head[u], w); head[u] = pos;
 26 } 
 27 
 28 void DFS(int u, int fa)
 29 {
 30     for (int it = head[u]; ~it; it = edge[it].nx)
 31     {
 32         int v = edge[it].v; 
 33         if (v == fa) continue;
 34         prefix[v] = prefix[u] ^ edge[it].w;
 35         DFS(v, u); 
 36     }
 37 }
 38 
 39 struct TRIE
 40 {
 41     int cnt;
 42     int T[N]; 
 43     struct node
 44     {
 45         int son[2]; 
 46         node()
 47         {
 48             memset(son, 0, sizeof son);
 49         }
 50     }a[N * 400]; 
 51 
 52     void Init()
 53     {
 54         cnt = n + 1; 
 55     }
 56 
 57     void Insert(int root, int x)
 58     {
 59         bitset <20> b; b = x; 
 60         for (int i = 19; i >= 0; --i)
 61         {
 62             if (!a[root].son[b[i]])
 63                 a[root].son[b[i]] = ++cnt;
 64             root = a[root].son[b[i]];
 65         }
 66     }
 67 
 68     int query(int root, int x)
 69     {
 70         bitset <20> b; b = x;
 71         int res = 0; 
 72         for (int i = 19; i >= 0; --i)
 73         {
 74             int id = b[i] ^ 1;
 75             bool flag = true;
 76             if (!a[root].son[id])
 77             {
 78                 flag = false;
 79                 id ^= 1;  
 80             }
 81             if (flag) res += 1 << i;
 82             root = a[root].son[id];
 83         }
 84         return res;  
 85     }
 86 }trie;
 87 
 88 int find(int x)
 89 {
 90     if (x != fa[x])
 91         fa[x] = find(fa[x]);
 92     return fa[x]; 
 93 }
 94 
 95 void Init()
 96 {
 97     memset(head, -1, sizeof head); pos = 0;
 98     prefix[1] = 0;
 99     trie.Init();
100 }
101 
102 void Run()
103 {
104     while (scanf("%d", &n) != EOF)
105     {
106         Init(); 
107         for (int i = 1, u, v, w; i < n; ++i)
108         {
109             scanf("%d%d%d", &u, &v, &w);
110             addedge(u, v, w);
111             addedge(v, u, w);
112             G[i] = Edge(u, v, w);
113         } 
114         DFS(1, 1);
115         for (int i = 1; i <= n; ++i)
116         {
117             fa[i] = i;
118             sz[i] = 1;
119             trie.T[i] = i;
120             trie.Insert(trie.T[i], prefix[i]);  
121             v[i].push_back(prefix[i]); 
122         }
123         sort(G + 1, G + n);
124         for (int i = 1; i < n; ++i)     
125         {
126             int x = G[i].u, y = G[i].v;
127             int fx = find(x), fy = find(y);  
128             if (sz[fx] > sz[fy]) swap(x, y), swap(fx, fy);
129             int res = 0; 
130             for (auto it : v[fx]) 
131             {
132                 res = max(res, trie.query(trie.T[fy], it));  
133             }
134             for (auto it : v[fx])
135             {
136                 trie.Insert(trie.T[fy], it);
137                 v[fy].push_back(it);
138             }
139             printf("%d%c", res, " \n"[i == n - 1]);
140             fa[fx] = fy; 
141             sz[fy] += sz[fx];
142         }
143     }
144 }
145 
146 int main()
147 {
148     #ifdef LOCAL
149         freopen("Test.in", "r", stdin);
150     #endif
151     
152     Run();
153     return 0;
154 }
View Code

 

 

E    Eustia of the Tarnished Wings

思路:排序,然后贪心合并即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1000010
 5 
 6 int n, m;
 7 int arr[N];
 8 
 9 void Run()
10 {
11     while (scanf("%d%d", &n, &m) != EOF)
12     {
13         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
14         sort(arr + 1, arr + 1 + n);
15         int res = 1;
16         for (int i = 2; i <= n; ++i) if (arr[i] - arr[i - 1] > m)
17             ++res;
18         printf("%d\n", res); 
19     }
20 }
21 
22 int main()
23 {
24     #ifdef LOCAL
25         freopen("Test.in", "r", stdin);
26     #endif    
27         
28     Run();
29     return 0;
30 }
View Code

 

F    Baldr Sky

留坑。

 

G    Kimi to Kanojo to Kanojo no Koi

留坑。

 

H    One Piece

留坑。

 

I    Steins;Gate

留坑。

 

J    Princess Principal

思路:用栈维护括号序列

其实假设存在合法文档 那么每一个括号都有一个唯一的对应括号

比如说 (())  肯定是中间两个匹配,再外面两个匹配

那么我们直接用栈维护一下,找到每个左括号的右匹配,以及找到每个有括号的左匹配,然后RMQ倍增维护最括号的最大右匹配,右括号的最小左匹配,如果最大值超过r 或者 最小值小于l 那么是不合法的

还有一种情况 就是 ([)  那么这三个括号都是不合法的

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 1000010
  5 #define INF 0x3f3f3f3f
  6 
  7 int n, m, q; 
  8 int arr[N], L[N], R[N];
  9 int mm[N];  
 10 stack <int> sta;
 11 
 12 void Init() 
 13 {
 14     mm[0] = -1;
 15     for (int i = 1; i <= n; ++i)
 16         mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1]; 
 17 }
 18 
 19 struct RMQ
 20 {
 21     int dp[N][20]; // 1 max 0 min 
 22     void Init(int n, int b[], int vis)  
 23     {
 24         for (int i = 1; i <= n; ++i)
 25             dp[i][0] = b[i];
 26         for (int j = 1; j <= mm[n]; ++j)
 27             for (int i = 1; i + (1 << j) - 1 <= n; ++i)
 28             {
 29                 if (vis) 
 30                     dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
 31                 else
 32                     dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); 
 33             }
 34     }
 35     
 36     int query(int x, int y, int vis)
 37     {
 38         int k = mm[y - x + 1];  
 39         if (vis)
 40             return max(dp[x][k], dp[y - (1 << k) + 1][k]);
 41         else
 42             return min(dp[x][k], dp[y - (1 << k) + 1][k]); 
 43     }
 44 }rmq[2]; 
 45 
 46 bool ok(int x, int y)
 47 { 
 48     if (rmq[0].query(x, y, 0) < x) return false;
 49     if (rmq[1].query(x, y, 1) > y) return false; 
 50     return true;  
 51 }
 52 
 53 void Run()
 54 {
 55     while (scanf("%d%d%d", &n, &m, &q) != EOF) 
 56     {
 57         memset(L, -1, sizeof L);
 58         memset(R, 0x3f, sizeof R);
 59         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
 60         for (int i = 1; i <= n; ++i)
 61         {
 62             if (arr[i] & 1)
 63             {
 64                 if (!sta.empty()) 
 65                 {
 66                     int top = sta.top(); sta.pop();
 67                     if (arr[i] / 2 == arr[top] / 2) L[i] = top;  
 68                 }
 69             }
 70             else
 71                 sta.push(i);         
 72         }
 73         while (!sta.empty()) sta.pop();
 74         for (int i = n; i >= 1; --i)
 75         {
 76             if (arr[i] % 2 == 0)
 77             {
 78                 if (!sta.empty())
 79                 {
 80                     int top = sta.top(); sta.pop();
 81                     if (arr[i] / 2 == arr[top] / 2) R[i] = top;
 82                 }
 83             }
 84             else
 85                 sta.push(i);
 86         }
 87         for (int i = 1; i <= n; ++i)  
 88         {
 89             if (arr[i] & 1) R[i] = -1; 
 90             else L[i] = INF;  
 91         }
 92         Init();
 93         rmq[0].Init(n, L, 0); 
 94         rmq[1].Init(n, R, 1);
 95         for (int i = 1, x, y; i <= q; ++i)
 96         {
 97             scanf("%d%d", &x, &y);
 98             puts(ok(x, y) ? "Yes" : "No");
 99         }
100     }
101 }
102 
103 int main()
104 {
105     #ifdef LOCAL
106         freopen("Test.in", "r", stdin);
107     #endif
108     
109     Run();
110     return 0;
111 }
View Code

 

 

K    Tengen Toppa Gurren Lagann

留坑。

 

L    New Game!

思路:分别处理 直线到圆的最短距离,圆到圆的最短距离,直线到直线的最短距离,然后跑最短路即可

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define N 1010
  5 #define INF 0x3f3f3f3f
  6  
  7 const double eps = 1e-8;
  8  
  9 int sgn(double x)
 10 {
 11     if (fabs(x) < eps) return 0;
 12     if (x < 0) return -1;
 13     else return 1;
 14 }
 15  
 16 struct Point
 17 {
 18     double x, y;
 19     Point() {}
 20     Point(double _x, double _y)
 21     {
 22         x = _x; y = _y;
 23     }
 24     double operator ^(const Point &b) const { return x * b.y - y * b.x; }
 25     double distance(Point p) { return hypot(x - p.x, y - p.y); }
 26     Point operator - (const Point &b) const { return Point(x - b.x, y - b.y); }
 27 };
 28  
 29 struct Line
 30 {
 31     Point s, e;
 32     Line() {}
 33     Line(double a, double b, double c)
 34     {
 35         if (sgn(a) == 0)
 36         {
 37             s = Point(0, -c / b);
 38             e = Point(1, -c / b);
 39         }
 40         else if (sgn(b) == 0)
 41         {
 42             s = Point(-c / a, 0);
 43             e = Point(-c / a, 1);
 44         }
 45         else
 46         {
 47             s = Point(0, -c / b);
 48             e = Point(1, (-c - a) / b);
 49         }
 50     }
 51     double length() { return s.distance(e); }
 52     double dispointtoline(Point p) { return fabs((p - s) ^ (e - s)) / length(); }
 53 }L[2];
 54  
 55 struct circle
 56 {
 57     Point p;
 58     double r;
 59     circle() {}
 60     circle(double x, double y, double _r)
 61     {
 62         p = Point(x, y);
 63         r = _r;
 64     }
 65 }arr[N];
 66  
 67  
 68 int n, A, B, C1, C2;
 69 double x, y, r;
 70 double G[N][N];
 71  
 72 void work0(int x, int y)
 73 {
 74     double dis = arr[x].p.distance(arr[y].p);
 75     G[x][y] = max(0.0, dis - arr[x].r - arr[y].r);
 76     G[y][x] = G[x][y];
 77 }
 78  
 79 void work1(int x, int y)
 80 {
 81     double dis = L[x].dispointtoline(arr[y].p);
 82     G[x][y] = max(0.0, dis - arr[y].r);
 83     G[y][x] = G[x][y];
 84 }
 85  
 86 double dis[N];
 87 bool used[N];
 88  
 89 void Dijkstra ()
 90 {
 91     for (int i = 0; i <= n + 1; ++i) dis[i] = INF * 1.0, used[i] = false;
 92     dis[0] = 0;
 93     for (int j = 0; j <= n + 1; ++j)
 94     {
 95         int k = -1;
 96         double Min = INF * 1.0;
 97         for (int i = 0; i <= n + 1; ++i)
 98         {
 99             if (!used[i] && dis[i] < Min)
100             {
101                 Min = dis[i];
102                 k = i;
103             }
104         }
105         used[k] = 1;
106         for (int i = 0; i <= n + 1; ++i)
107             if (!used[i] && dis[k] + G[k][i] < dis[i])
108                 dis[i] = dis[k] + G[k][i];
109     }
110 }
111  
112 void Run()
113 {
114     while (scanf("%d%d%d%d%d", &n, &A, &B, &C1, &C2) != EOF)
115     {
116         memset(G, 0x3f, sizeof G);
117         L[0] = Line(A, B, C1);
118         L[1] = Line(A, B, C2);
119         for (int i = 2; i <= n + 1; ++i)
120         {
121             scanf("%lf%lf%lf", &x, &y, &r);
122             arr[i] = circle(x, y, r);
123             G[i][i] = 0;
124         }
125         for (int i = 2; i <= n + 1; ++i)
126             for (int j = i + 1; j <= n + 1; ++j)
127                 work0(i, j);
128         for (int i = 0; i < 2; ++i)
129             for (int j = 2; j <= n + 1; ++j)
130                 work1(i, j);
131         G[0][1] = abs(C1 - C2) / sqrt(A * A + B * B);
132         G[1][0] = G[0][1];  
133         Dijkstra();
134         printf("%.10f\n", dis[1]);
135     }
136 }
137  
138 int main()
139 {
140     Run();
141     return 0;
142 }
View Code

 

posted @ 2018-10-01 16:25  Dup4  阅读(332)  评论(0编辑  收藏  举报