• 2012 MUTC 4 总结


    题库编号:hdu 4331~4339

    题解:http://page.renren.com/601081183/note/864084778?ref=minifeed&sfet=2012&fin=4&ff_id=601081183&feed=page_blog&tagid=864084778&statID=page_601081183_2&level=1

      好累的一个假期...今天中午没睡觉,下午比赛的时候还是很困的,不过不知道为什么没能睡着,所以回到宿舍写着写着这东西的时候就睡着了- -

      八月的第一场组队赛~

      今天的结果还是不错的,能做出3题,但是这还是远远不够的,因为做出的三题几乎所有校队的队伍都能做出来。赛后粗略看了一下题解,几题不会做的题涵盖的 数论,概率统计,树状数组,扩展KMP.......  好多东西要学啊!

      今天三题都是我过的,小有成就感~

      首先过的是1009,又是线段树!今天的线段树是要求出从某一点开始的最长相同子串的长度。刚开始的时候,因为以前没有解决过这样的问题,于是就当场和队友合作想解决这样的问题的线段树的一种更新方法。我当时首先想到的是每个结点标记该段内的串是否完全相同,这个的pushup是很容易就可以实现的。然后,就是query的时候是要如何统计。因为更新是单点更新,所以多个线段树的模板函数中,pushdown是不需要的,update也是很容易实现的。  好了,现在就是着重于query了。其实我们在每一种线段树的写法中,query都是要求进行一个区间的合并,然后在根的位置获得答案。现在我们记录了每段的覆盖情况,因此,在query合并区间时需要判断两段是否相连。这里有一个办法,就是用左儿子的末值(m)来减去k-1(或者当 k<=l 时的该段的长度)从而判断出左儿子相同的区间是否到左段的结尾,如果是就加上右儿子左边最长的相同区间的长度。

      这样的方法是没问题的,可是数据卡优化了,超时了。不过多得队友的提醒,所以我添加了一个标记变量,来记录每个段中从左边开始最长的相同区间的长度。添加了记忆化以后,效率优化了不少,然后当然就过了~

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cmath>
      4 #include <vector>
      5 #include <map>
      6 #include <queue>
      7 #include <list>
      8 #include <set>
      9 #include <cstring>
     10 #include <string>
     11 
     12 using namespace std;
     13 
     14 #define INF 0x7fffffff;
     15 #define max4(a, b, c, d) (max2(a, b) > max2(c, d) ? max2(a, b) : max2(c, d))
     16 #define min4(a, b, c, d) (min2(a, b) < min2(c, d) ? min2(a, b) : min2(c, d))
     17 #define feq(a, b) fabs((a) - (b)) < eps
     18 #define flq(a, b) (feq(a, b) || (a) < (b))
     19 #define reset(a) memset(a, 0, sizeof(a))
     20 #define fileout freopen("test.out", "w", stdout)
     21 #define filein freopen("test.in", "r", stdin)
     22 //segment tree
     23 #define lson l, m, rt << 1
     24 #define rson m + 1, r, rt << 1 | 1
     25 #define root 0, len - 1, 1
     26 
     27 #define debug 0
     28 
     29 const double eps = 1e-6;
     30 const int maxn = 1000005;
     31 
     32 int cov[maxn << 2], len[maxn << 2];
     33 char s[3][maxn];
     34 
     35 int max2(int a, int b){return a > b ? a : b;}
     36 int min2(int a, int b){return a < b ? a : b;}
     37 
     38 void up(int rt){
     39     if (cov[rt << 1]){
     40         len[rt] = len[rt << 1] + len[rt << 1 | 1];
     41     }
     42     else {
     43         len[rt] = len[rt << 1];
     44     }
     45     cov[rt] = (cov[rt << 1] && cov[rt << 1 | 1]) ? 1 : 0;
     46 }
     47 
     48 void build(int l, int r, int rt){
     49     if (l == r){
     50         if (s[1][l] == s[2][l]){
     51             cov[rt] = 1;
     52             len[rt] = 1;
     53         }
     54         else {
     55             cov[rt] = 0;
     56             len[rt] = 0;
     57         }
     58         return ;
     59     }
     60     int m = (l + r) >> 1;
     61 
     62     build(lson);
     63     build(rson);
     64 
     65     up(rt);
     66 }
     67 
     68 void update(int k, int l, int r, int rt){
     69     if (l == r){
     70         if (s[1][l] == s[2][l]){
     71             cov[rt] = 1;
     72             len[rt] = 1;
     73         }
     74         else {
     75             cov[rt] = 0;
     76             len[rt] = 0;
     77         }
     78         return ;
     79     }
     80     int m = (l + r) >> 1;
     81 
     82     if (k <= m){
     83         update(k, lson);
     84     }
     85     if (m < k){
     86         update(k, rson);
     87     }
     88     up(rt);
     89 }
     90 
     91 int query(int k, int l, int r, int rt){
     92     if (k <= l){
     93         return len[rt];
     94     }
     95     if (l == r){
     96         return len[rt];
     97     }
     98     int m = (l + r) >> 1;
     99     
    100     int tmp;
    101     if (k <= m){
    102        tmp = query(k, lson);
    103            #if debug
    104            printf("rtl %d  %d\n", rt, tmp);
    105            #endif
    106        int t = max2(k, l);
    107        if (tmp == m - t + 1){
    108            tmp += query(k, rson);
    109            #if debug
    110            printf("rtr %d  %d\n", rt, tmp);
    111            #endif
    112        }
    113     }
    114     else {
    115         tmp = query(k, rson);
    116     }
    117 
    118     #if debug
    119     printf("rt %d  %d\n", rt, tmp);
    120     #endif
    121     return tmp;
    122 }
    123 
    124 void deal(){
    125     int m, op, a, b;
    126     int len;
    127     
    128     scanf("%s%s", s[1], s[2]);
    129     len = min2(strlen(s[1]), strlen(s[2]));
    130     build(root);
    131         #if debug
    132         for (int j = 0; j < 15; j++){
    133             printf("%d", cov[j]);
    134         }
    135         puts("");
    136         #endif
    137 
    138     scanf("%d", &m);
    139     while (m--){
    140         scanf("%d", &op);
    141         if (op == 1){
    142             scanf("%d%d%s", &a, &b, s[0]);
    143             s[a][b] = s[0][0];
    144             update(b, root);
    145         }
    146         else if (op == 2){
    147             scanf("%d", &a);
    148             printf("%d\n", query(a, root));
    149         }
    150     }
    151 }
    152 
    153 int main()
    154 {
    155     int T;
    156 
    157     scanf("%d", &T);
    158     for (int i = 1; i <= T; i++){
    159         printf("Case %d:\n", i);
    160         deal();
    161         #if debug
    162         for (int j = 0; j < 15; j++){
    163             printf("%d", cov[j]);
    164         }
    165         puts("");
    166         #endif
    167 
    168     }
    169 
    170     return 0;
    171 }

      然后就是1004,一个简单的hash。刚开始,队友在我debug线段树那题的时候尝试打trie树上去,但是我现在算了一下,用这个数据结构应该是会超时的,因为大数据可以达到10^15,也就是树的深度可能达到depth=16的状况。哈希平均常数接近1,这样都要用掉1984ms了,如果是要trie树,那恐怕是要超时了。  当时我很快就打出了hash的函数,做过hash经典题目的话都可以看出这题就是数据变大了的那道经典hash(题意大概是给出一堆数,找出4个和为零的数)。不过我一开始hash开小了,才勉强大于要储存的个数40000,所以tle了一次。然后,简单的增大数组就轻松通过了。   对于hash参数的设置还是不熟,以后还得多练!

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cmath>
      4 #include <vector>
      5 #include <map>
      6 #include <queue>
      7 #include <list>
      8 #include <set>
      9 #include <cstring>
     10 #include <string>
     11 
     12 using namespace std;
     13 
     14 #define INF 0x7fffffff;
     15 #define max4(a, b, c, d) (max2(a, b) > max2(c, d) ? max2(a, b) : max2(c, d))
     16 #define min4(a, b, c, d) (min2(a, b) < min2(c, d) ? min2(a, b) : min2(c, d))
     17 #define feq(a, b) fabs((a) - (b)) < eps
     18 #define flq(a, b) (feq(a, b) || (a) < (b))
     19 #define reset(a) memset(a, 0, sizeof(a))
     20 #define fileout freopen("test.out", "w", stdout)
     21 #define filein freopen("test.in", "r", stdin)
     22 //segment tree
     23 #define lson l, m, rt << 1
     24 #define rson m + 1, r, rt << 1 | 1
     25 #define root 1, n, 1
     26 
     27 #define debug 0
     28 
     29 const double eps = 1e-6;
     30 const int maxn = 100001;
     31 
     32 int max2(int a, int b)
     33 {
     34     return a > b ? a : b;
     35 }
     36 
     37 int min2(int a, int b)
     38 {
     39     return a < b ? a : b;
     40 }
     41 const int size = 1000007;
     42 __int64 hash[size];
     43 bool ex[size];
     44 
     45 __int64 loc(__int64 s){
     46     __int64 h = (s << 2) % size;
     47 
     48     while (h < 0) h += size;
     49     while (h >= size) h -= size;
     50     while (ex[h] && hash[h] != s){
     51         h = (h + 1) % size;
     52     }
     53 
     54     return h;
     55 }
     56 
     57 void insert(__int64 s){
     58     __int64 pos = loc(s);
     59 
     60     hash[pos] = s;
     61     ex[pos] = true;
     62 }
     63 
     64 __int64 tmp[3][201];
     65 //__int64 sum[201 * 201];
     66 
     67 bool deal(){
     68     int n;
     69 
     70     memset(ex, 0, sizeof(ex));
     71     scanf("%d", &n);
     72     for (int i = 0; i < n; i++){
     73         scanf("%I64d", &tmp[0][i]);
     74     }
     75     for (int i = 0; i < n; i++){
     76         scanf("%I64d", &tmp[1][0]);
     77         for (int j = 0; j < n; j++){
     78             insert(tmp[1][0] + tmp[0][j]);
     79         }
     80     }
     81     #if debug
     82     puts("");
     83     for (int i = 0; i < size; i++){
     84         if (ex[i]) printf("%I64d\n", hash[i]);
     85     }
     86     puts("");
     87     #endif
     88     for (int i = 0; i < 3; i++){
     89         for (int j = 0; j < n; j++)
     90             scanf("%I64d", &tmp[i][j]);
     91     }
     92     for (int i = 0; i < n; i++){
     93         for (int j = 0; j < n; j++){
     94             for (int k = 0; k < n; k++){
     95                 if (ex[loc(-(tmp[0][i] + tmp[1][j] + tmp[2][k]))]) return true;
     96             }
     97         }
     98     }
     99     return false;
    100 }
    101 
    102 int main(){
    103     int T;
    104 
    105     scanf("%d", &T);
    106     for (int i = 1; i <= T; i++){
    107         if (deal()){
    108             printf("Yes\n");
    109         }
    110         else {
    111             printf("No\n");
    112         }
    113     }
    114     return 0;
    115 }

      最后的1007就不详细说了,因为我是借一位大牛的模板基本一样的套上去哈密顿(hamilton)函数过的。

    代码如下:

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cmath>
      4 #include <vector>
      5 #include <map>
      6 #include <queue>
      7 #include <list>
      8 #include <set>
      9 #include <cstring>
     10 #include <string>
     11 
     12 using namespace std;
     13 
     14 #define INF 0x7fffffff;
     15 #define max4(a, b, c, d) (max2(a, b) > max2(c, d) ? max2(a, b) : max2(c, d))
     16 #define min4(a, b, c, d) (min2(a, b) < min2(c, d) ? min2(a, b) : min2(c, d))
     17 #define feq(a, b) fabs((a) - (b)) < eps
     18 #define flq(a, b) (feq(a, b) || (a) < (b))
     19 #define reset(a) memset(a, 0, sizeof(a))
     20 #define fileout freopen("test.out", "w", stdout)
     21 #define filein freopen("test.in", "r", stdin)
     22 //segment tree
     23 #define lson l, m, rt << 1
     24 #define rson m + 1, r, rt << 1 | 1
     25 #define root 1, n, 1
     26 
     27 #define debug 1
     28 
     29 const double eps = 1e-6;
     30 
     31 
     32 int max2(int a, int b)
     33 {
     34     return a > b ? a : b;
     35 }
     36 
     37 int min2(int a, int b)
     38 {
     39     return a < b ? a : b;
     40 }
     41 
     42 const int maxn = 155;
     43 bool maz[maxn][maxn], vis[maxn];
     44 int s, t, len, tot, p, n;
     45 int ans[2][maxn];
     46 
     47 void expand(int x){
     48     bool flag;
     49 
     50     do{
     51         flag = false;
     52         if (!vis[x]) ans[p][tot++] = x;
     53         vis[x] = true;
     54         for (int i = 0; i < n; i++){
     55             if (maz[x][i] && !vis[i]){
     56                 x = i;
     57                 flag = true;
     58                 break;
     59             }
     60         }
     61     }while (flag);
     62 }
     63 
     64 void init (){
     65     memset(vis, 0, sizeof(vis));
     66     s = t = len = tot = p = 0;
     67     expand(s);
     68     reverse(ans[p], ans[p] + tot);
     69     expand(t);
     70     len = tot;
     71     s = ans[p][0];
     72     t = ans[p][len - 1];
     73 }
     74 
     75 void hamilton(){
     76     init();
     77     int i, j;
     78 
     79     while (len < n || !maz[s][t]){
     80         if (maz[s][t]){
     81             int u = -1, v = -1;
     82 
     83             for (i = 0; u == -1 && i < len; i++){
     84                 for (j = 0; j < n; j++){
     85                     if (!vis[j] && maz[ans[p][i]][j]){
     86                         u = i;
     87                         v = j;
     88                         break;
     89                     }
     90                 }
     91             }
     92             p = !p;
     93             tot = 0;
     94             for (i = u + 1; i < len; i++){
     95                 ans[p][tot++] = ans[!p][i];
     96             }
     97             for (i = 0; i <= u; i++){
     98                 ans[p][tot++] = ans[!p][i];
     99             }
    100             ans[p][tot++]  =v;
    101             vis[v] = true;
    102             len++;
    103 
    104         }
    105         else{
    106             for (i = 1; i < len; i++){
    107                 if (maz[s][ans[p][i]] && maz[t][ans[p][i - 1]]) break;
    108             }
    109             reverse(ans[p] + i, ans[p] + len);
    110         }
    111         s = ans[p][0], t = ans[p][len - 1];
    112     }
    113 }
    114 
    115 
    116 int main()
    117 {
    118     int a, b, m;
    119     while (~scanf("%d%d", &n, &m)){
    120         //n *= 2;
    121         memset(maz, false, sizeof(maz));
    122         for (int i = 0; i < m; i++){
    123             scanf("%d%d", &a, &b);
    124             --a, --b;
    125             maz[a][b] = maz[b][a] = true;
    126         }
    127         for (int i = 0; i < n; i++)maz[i][i] = false;
    128         hamilton();
    129         if (len < n)printf("no solution\n");
    130         else{
    131         for (int i = 0; i < len - 1; i++){
    132             printf("%d ", ans[p][i] + 1);
    133         }
    134         printf("%d\n", ans[p][len - 1] + 1);
    135         }
    136     }
    137 
    138     return 0;
    139 }

      不过这题过的挺惊险的,队友一开始想到用网络流增广路来找到连接成环的边,不过我随便出了个小数据就卡死了他.......汗啊!其实我没出数据就能想到算法的问题,不过解释了队友没有accept我的意见。然后就唯有找模板,不过我的模板没有圆桌问题的模板,而刚开始我又忘记了“哈密顿回路”这个词了 - -  结果在最后25min的时候我终于想到这个名了,这时队友告诉我他的模板里有哈密顿回路的模板,于是我们就从debug直接转变成打新代码了。    一个以前没试用的模板,还真怕模板不能用,不过我们师兄,秋教,他的模板真好,看上去应该是每个模板都能正确的,不像网上那些乱来的代码模板 = =,搞到我最近不断的在试。当然,顺便学各种算法。   最后匆匆忙忙的十来分钟打完函数,套进数据输入模式后测试了几组数据都正确,立马就提交了!最后在剩6分钟的时候Accepted了~~Yeah!~最后赶上了大队,因为这次大家都是三题四题的!

      好了,后面的路还长着,要练的还有很多!今天还有一个就是,我们三个人讨论好算法的分配了,希望这样的组织可以有效对付剩下的组队赛。

      当然,过了暑假以后还是要增强大家的个人综合能力的,这才是关键!一枝独秀,队里一人独强,这不是我喜欢的模式。因为纵观历史,合作是很重要的,合作成功与否的关键就是大家的水平必须要接近。这仅是我的观点。

     

    ——written by Lyon

    2012-8-2

  • 相关阅读:
    luogu P2685 [USACO07OPEN]抓牛Catch That Cow
    codevs 2021 中庸之道
    1018. 锤子剪刀布 (20)
    1017. A除以B (20)
    1016. 部分A+B (15)
    1013. 数素数 (20)
    1011. A+B和C (15)
    《C语言程序设计(第四版)》阅读心得(三)
    《C语言程序设计(第四版)》阅读心得(二)
    1008. 数组元素循环右移问题 (20)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/2012MUTC4_Lyon.html
Copyright © 2020-2023  润新知