• 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
    ", 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
    ", ans);
    232             }
    233         }
    234     }
    235     return 0;
    236 }
    View Code

    I - Tree

    题意:一棵树种,每个点有一个权值,表示可以向上跳几步,两种操作,一种是修改某点权值,还有一种是询问某个点需要跳几次跳出

    思路:DFS序分块,弹飞绵阳升级版,注意更新的时候,维护一个$In[u]$ 表示最远跳到块内是第几块,这样就不用多一个log

      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 == '
    ' || ch == '
    ' || ch == '	';
     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 
     50      void out(int x)
     51     {
     52         if (x / 10) out(x / 10);
     53         putchar(x % 10 + '0');
     54     }
     55 
     56     inline void print(int x)
     57     {
     58         out(x);
     59         puts("");
     60     }
     61     #undef BUF_SIZE
     62 }using namespace FastIO;
     63 
     64 #define N 100010
     65 #define DEG 20
     66 #define block 400
     67 
     68 int t, n, q;
     69 int a[N], b[N], In[N], Out[N], fa[N][20], deep[N], p[N], fp[N], cnt;
     70 vector <int> G[N];
     71 
     72 void Init()
     73 {
     74     for (int i = 1; i <= n; ++i) G[i].clear(); 
     75     cnt = 0; fa[1][0] = 1; deep[1] = 0;  
     76 }
     77 
     78 void DFS(int u)
     79 {
     80     p[u] = ++cnt;  
     81     fp[cnt] = u;
     82     for (int i = 1; i < DEG; ++i)
     83         fa[u][i] = fa[fa[u][i - 1]][i - 1];
     84     for (auto v : G[u]) if (v != fa[u][0])
     85     {
     86         deep[v] = deep[u] + 1; 
     87         DFS(v); 
     88     }
     89 }
     90 
     91 int GetK(int x, int k)
     92 {
     93     bitset <20> b; b = k;
     94     for (int i = 19; i >= 0; --i) if (b[i])
     95         x = fa[x][i];
     96     return x;
     97 }
     98 
     99 int query(int x)
    100 {
    101     int res = 0;
    102     x = p[x]; 
    103     while (x)
    104     {
    105         res += b[x];
    106         x = Out[x];
    107     }
    108     return res; 
    109 }
    110 
    111 void update(int x)
    112 {
    113     if (a[x] > deep[x])
    114     {
    115         b[p[x]] = 1;
    116         Out[p[x]] = 0;
    117         In[p[x]] = p[x]; 
    118     }
    119     else
    120     {
    121         int root = GetK(x, a[x]);
    122         if ((p[root] - 1) / block != (p[x] - 1) / block)
    123         {
    124             b[p[x]] = 1;
    125             Out[p[x]] = p[root];
    126             In[p[x]] = p[x]; 
    127         }
    128         else
    129         {
    130             b[p[x]] = b[p[root]] + 1;    
    131             Out[p[x]] = Out[p[root]];
    132             In[p[x]] = p[root];
    133         }
    134     }
    135     x = p[x];
    136     for (int i = x + 1; i <= n && (i - 1) / block == (x - 1) / block; ++i)  
    137     {
    138         if (In[i] != i)
    139         {
    140             b[i] = b[In[i]] + 1;
    141             Out[i] = Out[In[i]];
    142         }
    143     }
    144 }
    145 
    146 void Run()
    147 {
    148     read(t);
    149     while (t--)
    150     {
    151         read(n); Init();
    152         for (int i = 2; i <= n; ++i)
    153         {
    154             read(fa[i][0]);
    155             G[fa[i][0]].push_back(i);
    156         } DFS(1); 
    157         for (int i = 1; i <= n; ++i) read(a[i]);
    158         for (int i = 1; i <= n; ++i)
    159         {
    160             int x = fp[i]; 
    161             if (a[x] > deep[x])  
    162             {
    163                 b[i] = 1; 
    164                 Out[i] = 0;
    165                 In[i] = i;
    166                 continue;
    167             }
    168             int root = GetK(x, a[x]); 
    169             if ((p[root] - 1) / block != (i - 1) / block)
    170             {
    171                 b[i] = 1;
    172                 Out[i] = p[root];
    173                 In[i] = i;
    174             }
    175             else
    176             {
    177                 b[i] = b[p[root]] + 1;
    178                 Out[i] = Out[p[root]]; 
    179                 In[i] = p[root];
    180             }
    181         }
    182         read(q);
    183         for (int i = 1, op, x, v; i <= q; ++i)
    184         {
    185             read(op); read(x);
    186             if (op == 1) print(query(x));
    187             else
    188             {
    189                 read(v); 
    190                 a[x] = v;
    191                 update(x); 
    192             }
    193         }
    194     }
    195 }
    196 
    197 int main()
    198 {
    199     #ifdef LOCAL
    200         freopen("Test.in", "r", stdin); 
    201     #endif 
    202 
    203     Run();
    204     return 0;
    205 }
    View Code

    J - Sequence

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

    思路:考虑 最后一项最多有$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
    ", 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 == '
    ' || ch == '
    ' || ch == '	';
     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
    ", cnt);
    117         for(int i = 1; i <= k; ++i) printf("%d%c", ans[i], " 
    "[i == k]);
    118     }
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    SqlServer卸载实例
    java写的各种钟(收集)
    Codeforces 1003D Coins and Queries 【性质】
    Codeforces 997B Roman Digits【暴力】【枚举】
    洛谷 P2679 子串 【dp神题】【滚动数组】【2015 noip d2t2】
    复习图论
    Codeforces 1000D Yet Another Problem On a Subsequence 【dp】【组合数学】
    Codeforces 1000C Covered Points Count 【前缀和优化】
    Codeforces 999F Cards and Joy 【dp】【性质】
    Codeforces 999D Equalize the Remainders 【模拟】
  • 原文地址:https://www.cnblogs.com/Dup4/p/9768342.html
Copyright © 2020-2023  润新知