2018 Multi-University Training Contest 7 Solution

A - Age of Moyu

题意:给出一张图,从1走到n,如果相邻两次走的边的权值不同,花费+1, 否则花费相同,求最小花费

思路:用set记录有当前点的最小花费有多少种方案到达,然后最短路

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int INF = 0x3f3f3f3f;
  6 const int maxn = 2e5 + 10;
  7 
  8 struct Edge{
  9     int to, nxt, val;
 10     Edge(){}
 11     Edge(int to, int nxt, int val):to(to), nxt(nxt), val(val){};
 12 }edge[maxn << 1];
 13 
 14 set<int>s[maxn];
 15 int head[maxn], tot;
 16 
 17 void Init(int n)
 18 {
 19     for(int i = 0; i <= n; ++i) head[i] = -1, s[i].clear();
 20     tot = 0;
 21 }
 22 
 23 void addedge(int u, int v,int val)
 24 {
 25     edge[tot] = Edge(v, head[u], val);head[u] = tot++;
 26 }
 27 
 28 struct qnode{
 29     int v, c;
 30     int pre;
 31     int fa;
 32     qnode(){}
 33     qnode(int v, int c, int pre, int fa) :v(v), c(c), pre(pre), fa(fa){}
 34     bool operator < (const qnode &r) const
 35     {
 36         return c > r.c;
 37     }
 38 };
 39 
 40 int n, m;
 41 int dist[maxn];
 42 
 43 void BFS(int st)
 44 {
 45     for(int i = 1; i <= n; ++i) dist[i] = INF;
 46     priority_queue<qnode>q;
 47     dist[st] = 0;
 48     q.push(qnode(st, 0, 0, 0));
 49     while(!q.empty())
 50     {
 51         qnode tmp = q.top();
 52         q.pop();
 53         int u = tmp.v;
 54         if(tmp.c > dist[u]) continue;
 55         else if(tmp.c == dist[u])
 56         {
 57             if(s[u].find(tmp.pre) != s[u].end()) continue;
 58             s[u].insert(tmp.pre);
 59         }
 60         else 
 61         {
 62             dist[u] = tmp.c;
 63             s[u].clear();
 64             s[u].insert(tmp.pre);
 65         }
 66         for(int i = head[u]; ~i; i = edge[i].nxt)
 67         {
 68             int v = edge[i].to;
 69             int cost = edge[i].val;
 70             if(v == tmp.fa) continue;
 71             if(dist[u] + (cost != tmp.pre) <= dist[v])
 72             {
 73                 dist[v] = dist[u] + (cost != tmp.pre);
 74                 if(v != n)
 75                 {
 76                     q.push(qnode(v, dist[v], cost, u));
 77                 }
 78             }
 79         }
 80     }
 81 }
 82 
 83 int main()
 84 {
 85     int t;
 86     while(scanf("%d %d", &n, &m) != EOF)
 87     {
 88         Init(n);
 89         for(int i = 1; i <= m; ++i)
 90         {
 91             int u, v, w;
 92             scanf("%d %d %d", &u, &v ,&w);
 93             addedge(u, v, w);
 94             addedge(v, u, w);
 95         }
 96         BFS(1);
 97         if(dist[n] == INF) dist[n] = -1;
 98         printf("%d\n", dist[n]);
 99     }
100     return 0;
101 }
View Code

B - AraBellaC

留坑。

C - YJJ’s Stack

留坑。

D - Go to school

留坑。

E - GuGuFishtion

留坑。

F - Lord Li's problem

留坑。

G - Reverse Game

留坑。

H - Traffic Network in Numazu

题意:两种操作,第一种是更改一条边权的值,第二种是查询x-y的最短路径,给出的是一颗树加一条边

思路:将形成环的边单独拿出来考虑,那么考虑是否经过这条边使得答案更优,修改操作用线段树或者树状数组维护

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 
  7 const int maxn = 1e5 + 10;
  8 const int DEG = 20;
  9 
 10 struct EDGE{
 11     int u, v, w;
 12 }EDGE[maxn], TEMP;
 13 
 14 struct Edge{
 15     int to, nxt, val;
 16     Edge(){}
 17     Edge(int to, int nxt, int val) :to(to), nxt(nxt), val(val){}
 18 }edge[maxn << 1];
 19 
 20 int head[maxn], tot, cnt;
 21 int father[maxn];
 22 
 23 void Init(int n)
 24 {
 25     for(int i = 0; i <= n; ++i) head[i] = -1, father[i] = i;
 26     tot = cnt = 0;
 27 }
 28 
 29 int find(int x)
 30 {
 31     return x == father[x] ? father[x] : father[x] = find(father[x]);
 32 }
 33 
 34 void mix(int x,int y)
 35 {
 36     x = find(x), y = find(y);
 37     if(x != y) father[x] = y;
 38 }
 39 
 40 bool same(int x,int y)
 41 {
 42     return find(x) == find(y);
 43 }
 44 
 45 void addedge(int u, int v, int val)
 46 {
 47     edge[tot] = Edge(v, head[u], val); head[u] = tot++;
 48 }
 49 
 50 int dro[maxn];
 51 int ord[maxn], son[maxn];
 52 int fa[maxn][DEG];
 53 int deg[maxn];
 54 
 55 void DFS(int u, int pre)
 56 {
 57     ord[u] = ++cnt;
 58     dro[cnt] = u;
 59     for(int i = 1; i < DEG; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
 60     for(int i = head[u]; ~i; i = edge[i].nxt)
 61     {
 62         int v = edge[i].to;
 63         if(v == pre) continue;
 64         fa[v][0] = u;
 65         deg[v] = deg[u] + 1;
 66         DFS(v, u);
 67     }
 68     son[u] = cnt;
 69 }
 70 
 71 int LCA(int u, int v)
 72 {
 73     if(deg[u] > deg[v]) swap(u, v);
 74     int hu = deg[u], hv = deg[v];
 75     int tu = u, tv = v;
 76     for(int det = hv - hu, i = 0; det; det >>= 1, ++i)
 77     {
 78         if(det & 1)
 79         {
 80             tv = fa[tv][i];
 81         }
 82     }
 83     if(tu == tv) return tu;
 84     for(int i = DEG - 1; i >= 0; --i)
 85     {
 86         if(fa[tu][i] == fa[tv][i]) continue;
 87         tu = fa[tu][i];
 88         tv = fa[tv][i];
 89     }
 90     return fa[tu][0];
 91 }
 92 
 93 struct node{
 94     int l, r;
 95     ll val, lazy;
 96     node(){}
 97     node(int l,int r, ll val, ll lazy) :l(l), r(r), val(val), lazy(lazy){}
 98 }tree[maxn << 2];
 99 
100 void pushup(int id)
101 {
102     tree[id].val = tree[id << 1].val + tree[id << 1 | 1].val;
103 }
104 
105 void pushdown(int id)
106 {
107     if(tree[id].lazy)
108     {
109         ll lazy = tree[id].lazy;
110         tree[id << 1].val += lazy;
111         tree[id << 1 | 1].val += lazy;
112         tree[id << 1].lazy += lazy;
113         tree[id << 1 | 1].lazy += lazy;
114         tree[id].lazy = 0;
115     }
116 }
117 
118 void build(int id, int l, int r)
119 {
120     tree[id] = node(l, r, 0, 0);
121     if(l == r) return ;
122     int mid = (l + r) >> 1;
123     build(id << 1, l, mid);
124     build(id << 1 | 1, mid + 1, r);
125 }
126 
127 void update(int id, int l, int r, ll val)
128 {
129     if(l <= tree[id].l && r >= tree[id].r)
130     {
131         tree[id].val += val;
132         tree[id].lazy += val;
133         return ;
134     }
135     pushdown(id);
136     int mid = (tree[id].l + tree[id].r) >> 1;
137     if(mid >= l) update(id << 1, l, r, val);
138     if(r > mid) update(id << 1 | 1, l, r, val);
139     pushup(id);
140 }
141 
142 ll query(int id, int pos)
143 {
144     if(tree[id].l == pos && tree[id].r == pos)
145     {
146         return tree[id].val;
147     }
148     pushdown(id);
149     int mid = (tree[id].l + tree[id].r) >> 1;
150     if(pos <= mid) return query(id << 1, pos);
151     if(pos > mid) return query(id << 1 | 1, pos);
152     pushup(id);
153 }
154 
155 ll getdis(int u,int v)
156 {
157     int root = LCA(u, v);
158     return query(1, ord[u]) + query(1, ord[v]) - 2 * query(1, ord[root]);
159 }
160 
161 int n, q;
162 
163 int main()
164 {
165     int t;
166     scanf("%d", &t);
167     while(t--)
168     {
169         scanf("%d %d", &n, &q);
170         Init(n);
171         for(int i = 1; i <= n; ++i)
172         {
173             scanf("%d %d %d", &EDGE[i].u, &EDGE[i].v, &EDGE[i].w);
174             int u = EDGE[i].u, v = EDGE[i].v, w = EDGE[i].w;
175             if(same(u, v))
176             {
177                 TEMP = EDGE[i];
178                 continue;
179             }
180             mix(u, v);
181             addedge(u, v, w);
182             addedge(v, u, w);
183         }
184         fa[1][0] = 1;
185         deg[1] = 0;
186         DFS(1, -1);
187         build(1, 1, n);
188         for(int i = 1; i <= n; ++i)
189         {
190             int u = EDGE[i].u, v = EDGE[i].v, w = EDGE[i].w;
191             if(u == TEMP.u && v == TEMP.v) continue;
192             if(fa[u][0] == v)
193             {
194                 update(1, ord[u], son[u], w);
195             }
196             else if(fa[v][0] == u);
197             {
198                 update(1, ord[v], son[v], w);
199             }
200         }
201 //        for(int i = 1; i <= n; ++i) cout << ord[i] << endl;
202 //        for(int i = 1; i <= n; ++i) cout << i << " " << query(1, ord[i]) << endl;
203         while(q--)
204         {
205             int op, x, y;
206             scanf("%d %d %d", &op, &x ,&y);
207             if(op == 0)
208             {
209                 int u = EDGE[x].u, v = EDGE[x].v, w = EDGE[x].w;
210                 if(u == TEMP.u && v == TEMP.v)
211                 {
212                     EDGE[x].w = y;
213                     TEMP.w = y;
214                 }
215                 if(fa[u][0] == v)
216                 {
217                     update(1, ord[u], son[u], y - w);
218                 }
219                 else if(fa[v][0] == u)
220                 {
221                     update(1, ord[v], son[v], y - w);
222                 }
223                 EDGE[x].w = y;
224             }
225             else if(op == 1)
226             {
227                 ll ans = getdis(x, y);
228                 ans = min(ans, getdis(x, TEMP.u) + TEMP.w + getdis(y, TEMP.v));
229                 ans = min(ans, getdis(y, TEMP.u) + TEMP.w + getdis(x, TEMP.v));
230 
231                 printf("%lld\n", ans);
232             }
233         }
234     }
235     return 0;
236 }
View Code

I - Tree

留坑。

J - Sequence

题意:求$F_n = C * F_{n - 2} + D * F_{n - 1} + \lfloor{\frac {p}{n}}\rfloor$

思路:考虑 最后一项最多有$\sqrt n 项 按这个值分块矩阵快速幂即可$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 
 6 const ll MOD = (ll)1e9 + 7;
 7 
 8 int t, n;
 9 ll A, B, C, D, P;
10 
11 ll Biner(ll x)
12 {
13     ll l = x, r = n, res = l;
14     x = P / x;
15     while (r - l >= 0)
16     {
17         ll mid = (l + r) >> 1;
18         ll tmp = P / mid;
19         if (tmp >= x)
20         {
21             l = mid + 1;
22             res = mid;
23         }
24         else
25             r = mid - 1; 
26     }
27     return res;
28 }
29 
30 struct node
31 {
32     ll a[3][3];
33     node () 
34     {
35         memset(a, 0, sizeof a);
36     }
37     node operator * (const node &r) const
38     {
39         node ans = node();
40         for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) 
41            ans.a[i][j] = (ans.a[i][j] + a[i][k] * r.a[k][j] % MOD) % MOD;
42         return ans;
43     }    
44 }base;
45 
46 node qmod(node base, int n)
47 {
48     node res = node();
49     res.a[0][0] = B, res.a[0][1] = A; res.a[0][2] = 1;
50     while (n)
51     {
52         if (n & 1) res = res * base;
53         base = base * base;
54         n >>= 1;
55     }    
56     return res;
57 }
58 
59 ll work()
60 {
61     if (n == 1) return A;
62     if (n == 2) return B;
63     int l = 3, r;
64     while (l <= n)
65     {
66         r = Biner(l);
67         base.a[2][0] = P / l;        
68         node res = qmod(base, r - l + 1);
69         B = res.a[0][0], A = res.a[0][1];
70         l = r + 1;
71     }
72     return B;
73 }
74 
75 int main()
76 {
77     scanf("%d", &t);
78     while (t--)
79     {
80         scanf("%lld%lld%lld%lld%lld%d", &A, &B, &C, &D, &P, &n);
81         memset(base.a, 0, sizeof base.a);
82         base.a[0][0] = D, base.a[1][0] = C, base.a[0][1] = 1; base.a[2][2] = 1; 
83         printf("%lld\n", work());        
84     }
85     return 0;
86 }
View Code

K - Swordsman

题意:有五种攻击属性,怪物有五种防御属性,所有攻击属性要大于其对应的防御属性便能将其击杀,击杀后有经验加成,求最多杀死多少怪物

思路:用5个set 依次维护即可

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 namespace FastIO
  5 {
  6     #define BUF_SIZE 10000005
  7     bool IOerror = false;
  8     inline char NC()
  9     {
 10         static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
 11         if (p1 == pend)
 12         {
 13             p1 = buf;
 14             pend = buf + fread(buf, 1, BUF_SIZE, stdin);
 15             if (pend == p1)
 16             {
 17                 IOerror = true;
 18                 return -1;
 19             }
 20         }
 21         return *p1++;
 22     }
 23 
 24     inline bool blank(char ch)
 25     {
 26         return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
 27     }
 28 
 29     template <typename T>
 30     inline void read(T &x)
 31     {
 32         char ch;
 33         while (blank(ch = NC()));
 34         if (IOerror)
 35         {
 36             x = -1;
 37             return;
 38         }
 39         bool flag = false;
 40         if (ch == '-')
 41         {
 42             flag = true;
 43             ch = NC();
 44         }
 45         if (!isdigit(ch)) while (!isdigit(ch = NC()));
 46         for (x = ch - '0'; isdigit(ch = NC()); x = x * 10 + ch - '0');
 47         if (flag) x *= -1;
 48     }
 49     #undef BUF_SIZE
 50 }using namespace FastIO;
 51 
 52 const int maxn = 1e5 + 10;
 53 
 54 struct node{
 55     int id;
 56     int v;
 57     node(){}
 58     node(int id, int v) :id(id), v(v){}
 59     bool operator < (const node &r) const{
 60         return v > r.v;
 61     }    
 62 };
 63 
 64 priority_queue<node>q[10];
 65 
 66 int n, k;
 67 int ans[maxn];
 68 int arr[maxn][20];
 69 
 70 int main()
 71 {
 72     int t;
 73     read(t);
 74     while(t--)
 75     {
 76         read(n), read(k);
 77         for(int i = 1; i <= k; ++i) while(!q[i].empty()) q[i].pop();
 78         for(int i = 1; i <= k; ++i) read(ans[i]);
 79         for(int i = 1; i <= n; ++i)
 80         {
 81             for(int j = 1; j <= (k * 2); ++j)
 82             {
 83                 read(arr[i][j]);
 84             }
 85             q[1].push(node(i, arr[i][1]));
 86         }
 87         int cnt = 0;
 88         while(1)
 89         {
 90             bool flag = false;
 91             for(int i = 1; i <= k; ++i)
 92             {
 93                 while(!q[i].empty())
 94                 {
 95                     node tmp = q[i].top();
 96                     if(tmp.v <= ans[i])
 97                     {
 98                         if(i == k)
 99                         {
100                             cnt++;
101                             flag = true;
102                             for(int j = 1; j <= k; ++j) ans[j] += arr[tmp.id][j + k];
103                         }
104                         else
105                         {
106                             tmp.v = arr[tmp.id][i + 1];
107                             q[i + 1].push(tmp);
108                         }
109                         q[i].pop();
110                     }
111                     else break;
112                 }
113             }
114             if(!flag) break;
115         }
116         printf("%d\n", cnt);
117         for(int i = 1; i <= k; ++i) printf("%d%c", ans[i], " \n"[i == k]);
118     }
119     return 0;
120 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/9768342.html