zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/Dup4/p/9768342.html
Copyright © 2011-2022 走看看