zoukankan      html  css  js  c++  java
  • 2013暑假集训 第二场个人赛总结

      在开头问自己一句,题解还能坚持多少场呢?不管那样,能坚持就继续坚持下去,就算我不喜欢打字。

      好了,然后下面要正文了。7月18号,第二场个人赛。今天的比赛是另外一位10的大神yys出的,总体评价一下今天的题,虽然题目难度不算打,但是思维要求还是蛮高的,虽然有一道最小费用流的接近于模板题的题。然后,个人感觉,最近英语阅读水平降到不是路了,居然有一道大水题题意看了一场比赛都没看懂。_(:з」∠)_

    下面是题目来源,因为UESTC在比赛的过程中挂掉了,所以临时将DE两题改成SGU的两题了:

      IDOriginTitle
    30 / 100 Problem A CodeForces 48D A
    2 / 20 Problem B UVALive 3222 B
      2 / 43 Problem C CodeForces 121E C
        Problem D UESTC 1817 D
      0 / 4 Problem E UESTC 1806 E
      4 / 21 Problem F POJ 3680 F
      IDOriginTitle
        Problem A SGU 236 A
      4 / 59 Problem B SGU 186 B

      今天因为卡了一道KMP的水题,所以我的开始时间又迟了。囧rz。

      14点开始的比赛,我迟到了20分钟,去到那里,还是没有台式机给我用。_(:з」∠)_于是就只好布置我的电脑了。布置好以后,开始上去看题。21min,小马哥(一中大到华农的研究生大神,挺猛的)瞬秒了A(表一的A),于是我就去看A的题意~额。。比较蛋疼,表示自己英语真的不太好,开始担心起自己的四级过不过了。看了几分钟题目,有个叫做shuffle的单词一直没记住是什么意思,于是就拿起字典来查了。其实明白题意,这题超水,其实就是几个排列,把它们混在一起打乱了,把打乱了的结果给你,要求你把几个排列分离出来。排个序,然后从1开始堆上去,如果堆的过程中,其中一列断开了就不用继续了,否则继续堆,堆完以后对每一列编号就好了。然后就是十来分钟的敲代码时间了。1y是必然的~

      之后,我看了一下我隔壁的另一个大神hq,他做F了。题意是,给出若干带权重的线段,要求重叠的位置不超过k层,求最大的权重和。想了下,瞬间知道最小费用最大流不解释。可是,我。。额。。能说我没学网络流吗?然而我又不想抄模板过这题,于是就放弃这题了(回到宿舍以后抄了下模板就过了),转去做36min被人过了的B(表一的B)。我看了下题目,好熟悉的感觉,好像什么时候做过!嗯。。应该是2012的网络赛中的一题了!不过那时好像是用贪心,而且不用输出满足的情况,于是我就做这题去了。做这题用了整整2个钟,中间限时想到相同的区间要进行合并,然后再像活动安排那样贪心,然后又想到好像不能贪心,要dp,然后还要特判那些必然矛盾的情况。对了,说一下题意。B的题意是,有一些龟,告诉你他的前面和后面各有多少龟,那些龟有些是抱团的,抱团的一堆龟在同一个坐标位置上,要一起算。其实龟们不知道自己有没有说谎的,所以就要问你,他们说的话最少有多少句是假话。这题的做法是,先处理出区间(a + 1, n - b)(这个的意思是,这只龟跟一些其他龟同时在这个区间里),然后统计各个区间的出现的次数。当然,这个次数不能超过区间的大小!然后根据区间右端点对区间进行排序。对这些区间进行一个dp,如果区间 i 的右端点比 j 的左端点小(i < j),那么 j 这个区间就可以接在 i 的后面了,这时dp值为dp[i] + cnt[j],然后取最大的dp[i]即可。最后回溯一下,扫一遍输出即可。各种小错误,wa了8次才过。

      这时只剩1个多小时了,于是我就去看我比较有把握的C题。C的意思是,给出一串数,对它们的操作可以是对区间中的数增加同一个数,或者就是询问一个区间中只含数字4和7的数有多少个了。比赛的过程中,有两个12的师弟用暴力修改,树状数组查询的方法水过了,可是我居然没有那么无赖的去水。 - -||然而这题的正解是用线段树或者勉强能用块状数组(复杂度恰好允许)来做。http://codeforces.com/blog/entry/2956 不想写解释了,这里有C题的题解,请移步。

      结束战斗的时候只有两题,排大概第8的位置。只有两个3题的,还要都是我的队友。_(:з」∠)_最后10min实现逆袭,过掉了B(表二)好厉害。。。

      果然跟我说的一样,每次集训都是个好头可是就越打越差了。结束以后,把C、F和B(表二)都做了一下。C用了两种方法做,始终是线段树比较有优势。

    贴代码时间:

    A题代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 const int N = 111111;
     9 int rec[N];
    10 typedef pair<int, int> PII;
    11 PII arr[N], id[N];
    12 
    13 int main() {
    14     int n;
    15     while (cin >> n) {
    16         memset(arr, 0, sizeof(arr));
    17         for (int i = 0; i < n; i++) { scanf("%d", &arr[i].first); arr[i].second = i;}
    18         sort(arr, arr + n);
    19         memset(rec, 0, sizeof(rec));
    20         bool ok = true;
    21         int mx = 0;
    22         for (int i = 0, g = 1; i < n; i++) {
    23             id[i].first = arr[i].second;
    24             if (rec[g] != arr[i].first - 1) {
    25                 ok = false;
    26                 break;
    27             }
    28             rec[g]++;
    29             mx = max(g, mx);
    30             id[i].second = g++;
    31             if (arr[i].first != arr[i + 1].first) g = 1;
    32         }
    33         sort(id, id + n);
    34         if (ok) {
    35             printf("%d
    ", mx);
    36             for (int i = 0; i < n; i++) {
    37                 if (i) putchar(' ');
    38                 printf("%d", id[i].second);
    39             }
    40             puts("");
    41         } else puts("-1");
    42     }
    43     return 0;
    44 }
    View Code

    B题代码(有点乱):

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <map>
     6 
     7 using namespace std;
     8 
     9 typedef pair<int, int> PII;
    10 
    11 const int N = 1111;
    12 PII rec[N], tmp[N];
    13 bool vis[N], mk[N];
    14 map<PII, int> cnt_inv, ans;
    15 int dp[N];
    16 
    17 bool cmp(PII a, PII b) { return a.second < b.second;}
    18 
    19 int main() {
    20 //    freopen("in", "r", stdin);
    21     int n, x, y, t;
    22     while (cin >> n) {
    23         t = 0;
    24         memset(mk, 0, sizeof(mk));
    25         for (int i = 1; i <= n; i++) {
    26             cin >> x >> y;
    27             if (x + y >= n) continue;
    28             mk[i] = true;
    29             tmp[t++] = rec[i] = PII(x + 1, n - y);
    30         }
    31         sort(tmp, tmp + t);
    32         cnt_inv.clear();
    33         for (int i = 0; i < t; i++)    {
    34             if (cnt_inv.find(tmp[i]) == cnt_inv.end()) cnt_inv[tmp[i]] = 0;
    35             cnt_inv[tmp[i]] = min(cnt_inv[tmp[i]] + 1, tmp[i].second - tmp[i].first + 1);
    36         }
    37         int m = unique(tmp, tmp + t) - tmp;
    38         sort(tmp, tmp + m, cmp);
    39         memset(dp, 0, sizeof(dp));
    40         for (int i = 0; i < m; i++) {
    41             int mx = 0;
    42             for (int j = 0; j < i; j++) {
    43                 if (tmp[j].second < tmp[i].first) mx = max(mx, dp[j]);
    44             }
    45             dp[i] = mx + cnt_inv[tmp[i]];
    46         }
    47         int mxid = 0;
    48         for (int i = 1; i < m; i++) {
    49             if (dp[mxid] < dp[i]) mxid = i;
    50         }
    51         ans.clear();
    52         while (true) {
    53             if (dp[mxid] == cnt_inv[tmp[mxid]]) {
    54                 ans[tmp[mxid]] = cnt_inv[tmp[mxid]];
    55                 break;
    56             }
    57             for (int i = mxid - 1; i >= 0; i--) {
    58                 if (dp[mxid] - dp[i] == cnt_inv[tmp[mxid]] && tmp[i].second < tmp[mxid].first) {
    59                     ans[tmp[mxid]] = cnt_inv[tmp[mxid]];
    60                     mxid = i;
    61                     break;
    62                 }
    63             }
    64         }
    65         memset(vis, 0, sizeof(vis));
    66         int cntans = n;
    67         for (int i = 1; i <= n; i++) {
    68             if (mk[i] && ans.find(rec[i]) != ans.end()) {
    69                 if (ans[rec[i]] > 0) {
    70                     vis[i] = true;
    71                     ans[rec[i]]--;
    72                     cntans--;
    73                 }
    74             }
    75         }
    76         cout << cntans;
    77         for (int i = 1; i <= n; i++) if (!vis[i]) cout << ' ' << i;
    78         cout << endl;
    79 
    80     }
    81     return 0;
    82 }
    View Code

    C题代码(块状数组):

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 const int M = 11111;
     11 const int N = 111111;
     12 const int R = 333;
     13 
     14 vector<int> lucky;
     15 bool lc[M];
     16 
     17 bool test(int x) {
     18     while (x > 0) {
     19         if (x % 10 != 4 && x % 10 != 7) return false;
     20         x /= 10;
     21     }
     22     return true;
     23 }
     24 
     25 void PRE() {
     26     lucky.clear();
     27     for (int i = 1; i < M; i++)
     28         if (lc[i] = test(i)) lucky.push_back(i);
     29 }
     30 
     31 int cnt[R][M], late[R], rec[N];
     32 int n, m, r;
     33 
     34 void update(int L, int R, int d) {
     35     L--, R--;
     36     int a = L / r + 1, b = R / r;
     37     for (int i = a; i < b; i++) late[i] += d;
     38     if (a == b + 1) {
     39         for (int i = L; i <= R; i++) {
     40             cnt[b][rec[i]]--;
     41             rec[i] += d;
     42             cnt[b][rec[i]]++;
     43         }
     44     } else {
     45         for (int i = L, t = a * r; i < t; i++) {
     46             cnt[a - 1][rec[i]]--;
     47             rec[i] += d;
     48             cnt[a - 1][rec[i]]++;
     49         }
     50         for (int i = b * r; i <= R; i++) {
     51             cnt[b][rec[i]]--;
     52             rec[i] += d;
     53             cnt[b][rec[i]]++;
     54         }
     55     }
     56 //    for (int i = 0; i < n; i++) cout << rec[i] << ' '; cout << endl;
     57 //    for (int i = 0; i < r; i++) cout << late[i] << ' '; cout << endl;
     58 }
     59 
     60 int query(int L, int R) {
     61     L--, R--;
     62     int a = L / r + 1, b = R / r, ret = 0;
     63     vector<int>::iterator vi;
     64     for (int i = a; i < b; i++) {
     65         for (vi = lucky.begin(); vi != lucky.end(); vi++) {
     66             if (*vi - late[i] >= 0) ret += cnt[i][*vi - late[i]];
     67         }
     68     }
     69     if (a == b + 1) {
     70         for (int i = L; i <= R; i++) {
     71             if (lc[rec[i] + late[b]]) ret++;
     72         }
     73     } else {
     74         for (int i = L, t = a * r; i < t; i++) {
     75             if (lc[rec[i] + late[a - 1]]) ret++;
     76         }
     77         for (int i = b * r; i <= R; i++) {
     78             if (lc[rec[i] + late[b]]) ret++;
     79         }
     80     }
     81     return ret;
     82 }
     83 int main() {
     84 //    freopen("in", "r", stdin);
     85     PRE();
     86     while (~scanf("%d%d", &n, &m)) {
     87         memset(cnt, 0, sizeof(cnt));
     88         memset(late, 0, sizeof(late));
     89         r = (int) sqrt((double) n - 1) + 1;
     90         for (int i = 0; i < n; i++) {
     91             scanf("%d", &rec[i]);
     92             cnt[i / r][rec[i]]++;
     93         }
     94         char op[10];
     95         int L, R, d;
     96         while (m--) {
     97             scanf("%s", op);
     98             if (!strcmp(op, "count")) {
     99                 scanf("%d%d", &L, &R);
    100                 printf("%d
    ", query(L, R));
    101             }
    102             if (!strcmp(op, "add")) {
    103                 scanf("%d%d%d", &L, &R, &d);
    104                 update(L, R, d);
    105             }
    106         }
    107     }
    108     return 0;
    109 }
    View Code

    C题代码(线段树):

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <vector>
      6 
      7 using namespace std;
      8 
      9 #define lson l, m, rt << 1
     10 #define rson m + 1, r, rt << 1 | 1
     11 #define root 1, n, 1
     12 
     13 const int N = 111111;
     14 const int M = 11111;
     15 const int INF = 0x55555555;
     16 int lucky[33], mn[N << 2], lf[N << 2], late[N << 2], cnt[N << 2], rec[N << 2];
     17 
     18 bool test(int x) {
     19     while (x > 0) {
     20         if (x % 10 != 4 && x % 10 != 7) return false;
     21         x /= 10;
     22     }
     23     return true;
     24 }
     25 
     26 void PRE() {
     27     lucky[0] = 0;
     28     for (int i = 1; i < M; i++) if (test(i)) lucky[++lucky[0]] = i;
     29     lucky[++lucky[0]] = INF;
     30 //    for (int i = 1; i <= lucky[0]; i++) cout << lucky[i] << endl;
     31 }
     32 
     33 void up(int rt) {
     34     int ls = rt << 1, rs = rt << 1 | 1;
     35     if (mn[ls] <= mn[rs]) {
     36         lf[rt] = lf[ls];
     37         mn[rt] = mn[ls];
     38         cnt[rt] = cnt[ls];
     39         if (mn[ls] == mn[rs]) cnt[rt] += cnt[rs];
     40     } else {
     41         lf[rt] = lf[rs];
     42         mn[rt] = mn[rs];
     43         cnt[rt] = cnt[rs];
     44     }
     45 }
     46 
     47 void down(int rt) {
     48     if (late[rt]) {
     49         int ls = rt << 1, rs = rt << 1 | 1;
     50         mn[ls] -= late[rt];
     51         mn[rs] -= late[rt];
     52         late[ls] += late[rt];
     53         late[rs] += late[rt];
     54         rec[ls] += late[rt];
     55         rec[rs] += late[rt];
     56         late[rt] = 0;
     57     }
     58 }
     59 
     60 void fix1(int x) {
     61     if (x <= 1) return ;
     62     fix1(x >> 1);
     63     down(x >> 1);
     64 }
     65 
     66 void fix2(int x) {
     67     if (x <= 1) return ;
     68     up(x >> 1);
     69     fix2(x >> 1);
     70 }
     71 
     72 void update(int rt) {
     73     fix1(rt);
     74     int i = 1;
     75     while (lucky[i] < rec[rt]) i++;
     76     mn[rt] = lucky[i] - rec[rt];
     77 //    cout <<rec[rt] << ' ' << mn[rt] << endl;
     78     fix2(rt);
     79 }
     80 
     81 void build(int l, int r, int rt) {
     82     late[rt] = 0;
     83     if (l >= r) {
     84         scanf("%d", &rec[rt]);
     85         int i = 1;
     86         while (lucky[i] < rec[rt]) i++;
     87         mn[rt] = lucky[i] - rec[rt];
     88         cnt[rt] = 1;
     89         lf[rt] = rt;
     90         return ;
     91     }
     92     int m = l + r >> 1;
     93     build(lson);
     94     build(rson);
     95     up(rt);
     96 }
     97 
     98 void update(int L, int R, int d, int l, int r, int rt) {
     99     if (L <= l && r <= R) {
    100         mn[rt] -= d;
    101         late[rt] += d;
    102         rec[rt] += d;
    103         return ;
    104     }
    105     int m = l + r >> 1;
    106     down(rt);
    107     if (L <= m) update(L, R, d, lson);
    108     if (m < R) update(L, R, d, rson);
    109     up(rt);
    110 }
    111 
    112 int query(int L, int R, int l, int r, int rt) {
    113     if (L <= l && r <= R) return mn[rt] ? 0 : cnt[rt];
    114     int ret = 0, m = l + r >> 1;
    115     down(rt);
    116     if (L <= m && mn[rt << 1] == 0) ret = query(L, R, lson);
    117     if (m < R && mn[rt << 1 | 1] == 0) ret += query(L, R, rson);
    118     up(rt);
    119     return ret;
    120 }
    121 
    122 int query(int L, int R, int n) {
    123     while (mn[1] < 0) update(lf[1]);
    124     return query(L, R, root);
    125 }
    126 
    127 int main() {
    128 //    freopen("in", "r", stdin);
    129 //    freopen("out", "w", stdout);
    130     int n, m;
    131     PRE();
    132     while (~scanf("%d%d", &n, &m)) {
    133         build(root);
    134 //        cout << "built" << endl;
    135         char op[11];
    136         int l, r, x;
    137         while (m--) {
    138             scanf("%s", op);
    139             if (!strcmp(op, "count")) {
    140                 scanf("%d%d", &l, &r);
    141                 printf("%d
    ", query(l, r, n));
    142             }
    143             if (!strcmp(op, "add")) {
    144                 scanf("%d%d%d", &l, &r, &x);
    145                 update(l, r, x, root);
    146             }
    147 //            for (int i = 1; i <= 7; i++)cout << mn[i] << ' ' << lf[i] << ' ' << cnt[i] << endl;
    148         }
    149     }
    150     return 0;
    151 }
    View Code

    F题(最小费用流)代码:

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #include <queue>
     7 
     8 using namespace std;
     9 
    10 const int INF = 0x55555555;
    11 struct Edge {
    12     int s, t, cp, fl, co;
    13 } ;
    14 
    15 const int N = 888;
    16 struct MCMF {
    17     int n, m, s, t;
    18     vector<Edge> edges;
    19     vector<int> G[N];
    20     int inq[N], d[N], p[N], a[N];
    21 
    22     void init(int n) {
    23         this->n = n;
    24         for (int i = 0; i < n; i++) G[i].clear();
    25         edges.clear();
    26     }
    27     void AddEdge(int s, int t, int cp, int co) {
    28 //        cout << s << ' ' << t << ' ' << cp << ' ' << co << endl;
    29         edges.push_back((Edge) { s, t, cp, 0, co});
    30         edges.push_back((Edge) { t, s, 0, 0, -co});
    31         m = edges.size();
    32         G[s].push_back(m - 2);
    33         G[t].push_back(m - 1);
    34     }
    35     bool BF(int s, int t, int &fl, int &co) {
    36         for (int i = 0; i < n; i++) d[i] = INF;
    37         memset(inq, 0, sizeof(inq));
    38         d[s] = 0, inq[s] = 1, p[s] = 0, a[s] = INF;
    39         queue<int> Q;
    40         Q.push(s);
    41         while (!Q.empty()) {
    42             int u = Q.front();
    43 //            cout << u << endl;
    44             Q.pop();
    45             inq[u] = 0;
    46             for (int i = 0; i < G[u].size(); i++) {
    47                 Edge &e = edges[G[u][i]];
    48                 if (e.cp > e.fl && d[e.t] > d[u] + e.co) {
    49                     d[e.t] = d[u] + e.co;
    50                     p[e.t] = G[u][i];
    51                     a[e.t] = min(a[u], e.cp - e.fl);
    52                     if (!inq[e.t]) { Q.push(e.t); inq[e.t] = 1;}
    53                 }
    54             }
    55         }
    56         if (d[t] == INF) return false;
    57         fl += a[t];
    58         co += d[t] * a[t];
    59         int u = t;
    60         while (u != s) {
    61             edges[p[u]].fl += a[t];
    62             edges[p[u] ^ 1].fl -= a[t];
    63             u = edges[p[u]].s;
    64         }
    65         return true;
    66     }
    67     int MC(int s, int t) {
    68         int fl = 0, co = 0;
    69         while (BF(s, t, fl, co)) ;
    70         return co;
    71     }
    72 } mc;
    73 
    74 int main() {
    75 //    freopen("in", "r", stdin);
    76 //    freopen("out", "w", stdout);
    77     int T, n, k, a[N], b[N], w[N];
    78     cin >> T;
    79     while (T-- && cin >> n >> k) {
    80         mc.init(n + 5 << 1);
    81         for (int i = 0; i < n; i++) cin >> a[i] >> b[i] >> w[i];
    82         for (int i = 0; i < n; i++) {
    83             mc.AddEdge(0, i + 1, 1, 0);
    84             mc.AddEdge(i + 1, i + n + 1, 1, -w[i]);
    85             for (int j = 0; j < n; j++) if (i != j && b[i] <= a[j]) mc.AddEdge(i + n + 1, j + 1, 1, 0);
    86             mc.AddEdge(i + n + 1, n << 1 | 1, 1, 0);
    87         }
    88         mc.AddEdge(n << 1 | 1, n + 1 << 1, k, 0);
    89 //        cout << "built" << endl;
    90         cout << -mc.MC(0, n + 1 << 1) << endl;
    91     }
    92     return 0;
    93 }
    View Code

    B题(表二,贪心)代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 
     8 bool cmp(int a, int b) { return a > b;}
     9 
    10 int main() {
    11     int rec[111], n;
    12     while (cin >> n) {
    13         for (int i = 0; i < n; i++) cin >> rec[i];
    14         sort(rec, rec + n, cmp);
    15         int t = 0, ans = 0;
    16         while (t < n - 1) {
    17             t++;
    18             rec[t] = 100;
    19             ans++;
    20             if (rec[n - 1] == 1) n--;
    21             else rec[n - 1]--;
    22         }
    23         cout << ans + max(0, n - t - 1) << endl;
    24     }
    25     return 0;
    26 }
    View Code

    ——written by Lyon

  • 相关阅读:
    [转]修改远程桌面端口
    [转]3个著名加密算法(MD5、RSA、DES)的解析
    [转]常见HTTP状态(如200,304,404,503)
    用 SqlConnectionStringBuilder 来写连接字符串,向连接字符串添加设置
    windows 设置ipsec防火墙
    网络带宽单位换算
    Linux 检查端口gps命令
    设置Linux防火墙
    windows 服务器同步互联网时间
    windows 路由转发
  • 原文地址:https://www.cnblogs.com/LyonLys/p/2013_07_18_Lyon.html
Copyright © 2011-2022 走看看