zoukankan      html  css  js  c++  java
  • 8月5日集训队个人赛第七场解题报告

    A Codeforces 204A

    简单的数位DP。从高位到低位扫一遍就可以了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 typedef long long LL;
     4 const int maxn = 20;
     5 LL p[maxn];
     6 
     7 LL DP(LL x){
     8     int bit[20], cnt = 0;
     9     for(LL n = x; n; bit[cnt ++] = n%10, n/=10);
    10     if(cnt==1) return x - 1;
    11     LL ans = 9;
    12     for(int i = 2; i <= cnt - 1; i ++)
    13         ans = ans + 9 * p[i-2];
    14     for(int i = cnt - 1, j = 1; i > 0; i --, j ++){
    15         if(i == cnt - 1) ans = ans + (bit[i] - 1) * p[cnt - j - 1];
    16         else ans = ans + bit[i] * p[cnt - j - 1];
    17     }
    18     if(bit[0] > bit[cnt-1]) ans ++;
    19     return ans;
    20 }
    21 
    22 int main(){
    23     p[0] = 1;
    24     for(int i = 1; i <= 18; i ++) p[i] = p[i-1] * 10;
    25     for(LL l, r; scanf("%I64d%I64d", &l, &r)!=EOF; printf("%I64d
    ", DP(r+1) - DP(l)));
    26     return 0;
    27 }
    View Code

    B Codeforces 120F

    树形DP,寻找一棵树的最长直径。dp[i][2],0表示以i为根的子树中最长的链,1表示以i为根的子树中次长链,其中最长链与次长链没有共同的边只有一个i点位公共的根。第一次dfs求dp数组,第二次dfs时求以每个点为根的时候的最长直径,答案在i的子树中,最长链与次长链的和或者最长链与从父亲边过来的最长的链的和。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 100+5;
     7 int f[maxn], e[maxn*2], t[maxn*2];
     8 int d[maxn][2], c[maxn][2];
     9 int tot;
    10 
    11 void add(int u, int v){
    12     e[tot] = f[u];
    13     t[tot] = v;
    14     f[u] = tot ++;
    15 }
    16 void dfs1(int u, int fa){
    17     d[u][0] = d[u][1] = 0;
    18     c[u][0] = c[u][1] = 0;
    19     for(int i = f[u]; i != -1; i = e[i]){
    20         int v = t[i];
    21         if(v==fa) continue;
    22         dfs1(v, u);
    23         if(d[v][0] + 1 <= d[u][1]) continue;
    24         d[u][1] = d[v][0] + 1;
    25         c[u][1] = v;
    26         if(d[u][1] > d[u][0]){
    27             swap(d[u][1], d[u][0]);
    28             swap(c[u][1], c[u][0]);
    29         }
    30     }
    31 }
    32 void dfs2(int u, int fa, int l, int &ans){
    33     ans = max(ans, d[u][0] + d[u][1]);
    34     ans = max(ans, d[u][0] + l);
    35     for(int i = f[u]; i != -1; i=e[i]){
    36         int v = t[i];
    37         if(v==fa) continue;
    38         if(v != c[u][0])
    39             dfs2(v, u, max(l + 1, d[u][0] + 1), ans);
    40         else
    41             dfs2(v, u, max(l + 1, d[u][1] + 1), ans);
    42     }
    43 }
    44 int main(){
    45     freopen("input.txt", "r", stdin);
    46     freopen("output.txt", "w", stdout);
    47     for(int n, ans; scanf("%d", &n)!=EOF;){
    48         ans = 0;
    49         for(int i = 1, m; i <= n; i ++){
    50             scanf("%d", &m);
    51             memset(f, -1, sizeof(f));tot=0;
    52             for(int i = 1, u, v; i < m; i ++){
    53                 scanf("%d%d", &u, &v);
    54                 add(u, v);
    55                 add(v, u);
    56             }
    57             dfs1(1, 0);
    58             int tmp = 0; dfs2(1, 0, 0, tmp);
    59             ans = ans + tmp;
    60         }
    61         printf("%d
    ", ans);
    62     }
    63     return 0;
    64 }
    View Code

    C Codeforces 29D

    LCA+模拟。由于点比较少,直接用并查集,不适用路径压缩,并且对每个点维护一个到根的距离。然后每次就直接查最近公共祖先,然后模拟走就可以了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 #define maxn 310
     6 
     7 int dfn[maxn], f[maxn], head[maxn], order[maxn];
     8 int euler[maxn*2], e[maxn*2], g[maxn*2];
     9 int tot, pos;
    10 int stack[maxn];
    11 
    12 void add(int u, int v){
    13     e[tot] = head[u];
    14     g[tot] = v;
    15     head[u] = tot ++;
    16 }
    17 
    18 int dfs(int v, int fa, int depth){
    19     dfn[v] = depth + 1;
    20     f[v] = fa;
    21     int son = 0, flag = 1;
    22     for(int i = head[v] ; i != -1; i = e[i]){
    23         int u = g[i];
    24         if(u==fa) continue;
    25         son += dfs(u, v, depth+1);
    26         flag = 0;
    27     }
    28     son += flag;
    29     return son;
    30 }
    31 
    32 int getAncestor(int u, int v){
    33     for(;dfn[u]!=dfn[v];){
    34         if(dfn[u]>dfn[v]) u = f[u];
    35         else v = f[v];
    36     }
    37     for(;u!=v; u = f[u], v = f[v]);
    38     return u;
    39 }
    40 
    41 void up(int v, int fa){
    42     for(v = f[v];v!=fa;v = f[v]){
    43         euler[pos ++] = v;
    44     }
    45     euler[pos ++] = fa;
    46 }
    47 void down(int v, int fa){
    48     int top = 0;
    49     for(v; v != fa; v = f[v]){
    50         stack[top++] = v;
    51     }
    52     for(;top; euler[pos ++] = stack[--top]);
    53 }
    54 
    55 int main(){
    56     //freopen("test.in", "r", stdin);
    57     for(int n; scanf("%d", &n)!=EOF;){
    58         tot = pos = 0;
    59         memset(head, -1, sizeof(head));
    60         for(int i = 1, x, y; i < n; i ++){
    61             scanf("%d%d", &x, &y);
    62             add(x, y);
    63             add(y, x);
    64         }
    65         int leafn = dfs(1, 1, 1);
    66         for(int i = 0; i < leafn; i ++){
    67             scanf("%d", &order[i]);
    68         }
    69         euler[pos ++] = 1;
    70         down(order[0], 1);
    71         for(int i = 1, last = order[0]; i < leafn; i ++){
    72             int ancestor = getAncestor(last, order[i]);
    73             //printf(">> ancestor: %d
    ", ancestor);
    74             up(last, ancestor);
    75             down(order[i], ancestor);
    76             last = order[i ];
    77             if(pos > 2*n-1){
    78                 break;
    79             }
    80         }
    81         up(order[leafn-1], 1);
    82         if(pos > 2*n-1){
    83             printf("-1
    ");
    84         }
    85         else{
    86             for(int i = 0; i < pos; i ++){
    87                 printf("%d ", euler[i]);
    88             }
    89             printf("
    ");
    90         }
    91     }
    92     return 0;
    93 }
    View Code

    D Codeforces 128B

    优先队列模拟就可以了。先把长度为1的丢进去,然后每次取出一个元素后,进行扩展(+1位)

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <queue>
     4 #include <algorithm>
     5 #include <string>
     6 #include <iostream>
     7 #include <functional>
     8 using namespace std;
     9 
    10 struct Node{
    11     string first;
    12     int second;
    13     bool operator<(const Node &a)const{
    14         return first > a.first;
    15     }
    16 };
    17 Node make_node(string s, int p){
    18     Node a;
    19     a.first = s, a.second = p;
    20     return a;
    21 }
    22 
    23 int main(){
    24     string a, s = "";
    25     int k, i, pos;
    26     cin>>a; cin>>k;
    27     priority_queue<Node> Q;
    28     for(i = 0; i < a.size(); i ++){
    29         Q.push(make_node(s + a[i], i));
    30     }
    31     for(i = 0; i < k - 1 && !Q.empty(); i ++){
    32         s = Q.top().first;
    33         pos = Q.top().second;
    34         Q.pop();
    35         if(pos + 1 < a.size()){
    36             Q.push(make_node(s + a[pos + 1], pos + 1));
    37         }
    38     }
    39     if(i < k - 1 || i == k - 1 && Q.empty()){
    40         cout<<"No such line."<<endl;
    41     }
    42     else cout<<Q.top().first<<endl;
    43     return 0;
    44 }
    View Code

    E Codeforces 178B1~178B3

    求从一个点到另一个点的路径上最少经过的割边是多少。

    先用tarjan求边双连通分量,然后染色,将割边记录下来,然后建树。然后对树做欧拉环游,并得到每个点到根的距离,对得到的序列做RMQ,对于询问x, y

    其结果就是dfn[col[x]] + dfn[col[y]] - dfn[ance],其中ance时col[x], col[y]的最近公共祖先。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int maxn = 100005;
     6 const int maxm = 100005;
     7 typedef int arr[maxn];
     8 arr head, dfn, low, col, st;
     9 int top, depth, color, tot, cnt;
    10 pair<int, int> e[maxm*2], bridge[maxn];
    11 int euler[maxn*3], d[maxn*3][30], pos;
    12 
    13 void add(int x, int y){
    14     e[tot] = make_pair(head[x], y);
    15     head[x] = tot ++;
    16 }
    17 void tarjan(int u, int f){
    18     dfn[u] = low[u] = ++depth;
    19     st[++top] = u;
    20     for(int i = head[u]; i != -1; i = e[i].first){
    21         int v = e[i].second;
    22         if(v==f) continue;
    23         if(!dfn[v]){
    24             tarjan(v, u);
    25             low[u] = min(low[v], low[u]);
    26         }
    27         else low[u] = min(low[u], dfn[v]);
    28         if(low[v] > dfn[u])
    29             bridge[cnt ++] = make_pair(u, v);
    30     }
    31     if(dfn[u] == low[u]){
    32         int x; color ++;
    33         do{
    34             col[x = st[top--]] = color;
    35         }while(x != u);
    36     }
    37 }
    38 void dfs(int u, int f){
    39     euler[++ pos] = u; low[u] = pos;
    40     for(int i = head[u]; i != -1; i = e[i].first){
    41         int v = e[i].second;
    42         if(v==f) continue;
    43         dfn[v] = dfn[u] + 1;
    44         dfs(v, u);
    45         euler[++pos] = u;
    46     }
    47 }
    48 void RMQ_init(){
    49     for(int i = 1; i <= pos; i ++) d[i][0] = i;
    50     for(int j = 1; (1<<j) <= pos; j ++){
    51         for(int i = 1; i + j - 1<= pos; i ++){
    52             if(dfn[euler[d[i][j-1]]] < dfn[euler[d[i + (1<<(j-1))][j-1]]]){
    53                 d[i][j] = d[i][j-1];
    54             }
    55             else d[i][j] = d[i + (1<<(j-1))][j-1];
    56         }
    57     }
    58 }
    59 int RMQ(int L, int R){
    60     int k = 0;
    61     if(L > R) swap(L, R);
    62     while((1<<(k+1)) <= R-L+1) k ++;
    63     return dfn[euler[d[L][k]]] < dfn[euler[d[R-(1<<k)+1][k]]] ? d[L][k] : d[R-(1<<k)+1][k];
    64 }
    65 int main(){
    66     //freopen("test.in", "r", stdin);
    67     for(int n, m, Q; scanf("%d%d", &n, &m)!=EOF; ){
    68         depth = color = tot = top = cnt =0;
    69         for(int i = 1; i <= n; i ++){
    70             head[i] = -1, dfn[i] = 0;
    71         }
    72         for(int i = 1, x, y; i <= m; i ++){
    73             scanf("%d%d", &x, &y);
    74             add(x, y);
    75             add(y, x);
    76         }
    77         tarjan(1, -1);
    78         tot = 0;
    79         for(int i = 0; i <= color; i ++){
    80             head[i] = -1;
    81             dfn[i] = 0;
    82         }
    83         for(int i = 0; i < cnt; i ++){
    84             add(col[bridge[i].first], col[bridge[i].second]);
    85             add(col[bridge[i].second], col[bridge[i].first]);
    86         }
    87         pos = dfn[1] = 0;
    88         dfs(1, 0);
    89         RMQ_init();
    90         scanf("%d", &Q);
    91         for(int i = 1, x, y; i <= Q; i ++){
    92             scanf("%d%d", &x, &y);
    93             int ance = RMQ(low[col[x]], low[col[y]]); ance = euler[ance];
    94             printf("%d
    ", dfn[col[x]] + dfn[col[y]] - 2 * dfn[ance]);
    95         }
    96     }
    97     return 0;
    98 }
    View Code

    F URAL 1671

    并查集。倒着搞就是了,先将没有删除的边合并,然后按照从后往前加边就是了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 100005;
     7 const int maxm = 100000+10;
     8 int f[maxn], h[maxm], s[maxm];
     9 bool mark[maxm];
    10 pair<int, int> edge[maxm];
    11 
    12 int find(int x){
    13     return x ==f[x] ? x : (f[x] = find(f[x]));
    14 }
    15 
    16 int main(){
    17     for(int n, m;scanf("%d%d", &n, &m)!=EOF;){
    18         for(int i = 1; i <= n; i ++) f[i] = i;
    19         for(int i = 1, x, y; i <= m; i ++){
    20             scanf("%d%d", &x, &y);
    21             edge[i] = make_pair(x, y);
    22         }
    23         int q, cnt = n; scanf("%d", &q);
    24         for(int i = 1, x; i <= q; i ++){
    25             scanf("%d", &x);
    26             mark[x] = 1;
    27             h[i] = x;
    28         }
    29         for(int i = 1; i <= m; i ++){
    30             if(!mark[i]){
    31                 int x = find(edge[i].first);
    32                 int y = find(edge[i].second);
    33                 if(x == y) continue;
    34                 f[x] = y;
    35                 cnt --;
    36             }
    37         }
    38         for(int i = q; i >= 1; i --){
    39             s[i] = cnt;
    40             int x = find(edge[h[i]].first);
    41             int y = find(edge[h[i]].second);
    42             if(x==y) continue;
    43             f[x] = y;
    44             cnt --;
    45         }
    46         for(int i = 1; i <= q; i ++){
    47             if(i != 1) printf(" ");
    48             printf("%d", s[i]);
    49         }
    50         printf("
    ");
    51     }
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    软件工程阅读笔记02
    软件工程阅读笔记01
    四则运算二
    第十七周学习进度条
    个人总结以及建议
    写api接口神器--带你5分钟了解swagger
    nginx的配置和基本参数说明
    larval 使用redis做缓存
    Laravel——缓存使用
    开启redis-server提示 # Creating Server TCP listening socket *:6379: bind: Address already in use--解决方法
  • 原文地址:https://www.cnblogs.com/bootstar/p/3237863.html
Copyright © 2011-2022 走看看