20140426组队赛总结

【首先检讨,昨天晚上误解以为今天没有比赛,所以到实验室已经1个小时过去了,就lh大仙一个单刷,Orz】

【然后是来的路上惹怒了niuniu,我的错】

 

本场比赛是11年hnu出的多校训练,往往多校训练的题目质量都是比较好的,水题不会太多,考的知识面比较广和深或者很偏很难。

 

由于到实验室迟到了1个小时,lh大仙挂了B,H题和I都被秒了,于是我看了H,过了之后发现F题被dongfang队秒掉,我又转看F,由此陷入了深深的泥潭。Orz,膜拜F题1A!之后就去401一起做题了。

 

【H题】给定数N<=10^9,求a^2+b^2 = N的序对数,注意a,b可以正负。显然sqrt(N)暴力即可。59min, 1A。

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<string.h>
 4 
 5 long long sq[1001000];
 6 int cnt;
 7 int judge(int m)
 8 {
 9     int l = 1, r = cnt;
10     while (l <= r)
11     {
12         int mid = (l + r)/2;
13         if (sq[mid] == m)
14         {
15             return true;
16         }
17         if (sq[mid] < m){
18             l = mid + 1;
19         }else{
20             r = mid - 1;
21         }
22     }
23     return false;
24 }
25 int calc(long long n)
26 {
27     if (n == 0)
28         return 1;
29     int res = 0;
30     for  (int i=1;i*i<=n;i++)
31     {
32         if (i*i == n)
33         {
34             res += 4;
35         }else{
36             if (judge(n - i * i))
37             {
38                 if (i*i == n - i*i)
39                     res += 4;
40                 else
41                     res += 4;
42             }
43         }
44     }
45 
46     return res;
47 }
48 int main()
49 {
50     cnt = 0;
51     for (long long i=1;i*i<=1000000000;i++)
52     {
53         sq[++cnt] = i * i;
54     }
55     long long n;
56     while (scanf("%I64d",&n)==1)
57     {
58         printf("%d\n",calc(n));
59     }
60     return 0;
61 }
H(wangsouc)

 

【此时I题】已经被大仙秒掉,后面知道这个题是白书上的原题,他直接抄的代码。

I题,给定N个点,M条边的有向图,问至少加入多少条边,使得整个图为强连通的。scc+统计入度和出度为0的点,然后YY。模板题。61min,1A。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <string.h>
  6 #include <string>
  7 #include <vector>
  8 #include <stack>
  9 
 10 using namespace std;
 11 
 12 const int MAXN = 100000 + 10;
 13 vector<int> G[MAXN];
 14 int T, n, m;
 15 int pre[MAXN], lowlink[MAXN], sccno[MAXN], dfs_clock, scc_cnt;
 16 int in0[MAXN], out0[MAXN];
 17 stack <int> S;
 18 
 19 void dfs(int u)
 20 {
 21     pre[u] = lowlink[u] = ++dfs_clock;
 22     S.push(u);
 23     for (int i = 0; i < G[u].size(); i++)
 24     {
 25         int v = G[u][i];
 26         if (!pre[v])
 27         {
 28             dfs(v);
 29             lowlink[u] = min(lowlink[u], lowlink[v]);
 30         }
 31         else if (!sccno[v])
 32         {
 33             lowlink[u] = min(lowlink[u], pre[v]);
 34         }
 35     }
 36 
 37     if (lowlink[u] == pre[u])
 38     {
 39         scc_cnt++;
 40         for (;;)
 41         {
 42             int x = S.top(); S.pop();
 43             sccno[x] = scc_cnt;
 44             if (x == u) break;
 45         }
 46     }
 47 }
 48 
 49 void find_scc(int n)
 50 {
 51     dfs_clock = scc_cnt = 0;
 52     memset(sccno, 0, sizeof(sccno));
 53     memset(pre, 0, sizeof(pre));
 54     for (int i = 0; i < n; i++)
 55     {
 56         if (!pre[i])dfs(i);
 57     }
 58 }
 59 
 60 void input()
 61 {
 62     while (scanf("%d %d", &n, &m) != EOF)
 63     {
 64         for (int i = 0; i < n; i++)
 65         {
 66             G[i].clear();
 67         }
 68         for (int i = 0; i < m; i++)
 69         {
 70             int u, v;
 71             scanf("%d %d", &u, &v); u--; v--;
 72             G[u].push_back(v);
 73         }
 74 
 75         find_scc(n);
 76 
 77         for (int i = 1; i <= scc_cnt; i++) in0[i] = out0[i] = 1;
 78         for (int u = 0; u < n; u++)
 79         {
 80             for (int i = 0; i < G[u].size(); i++)
 81             {
 82                 int v = G[u][i];
 83                 if (sccno[u] != sccno[v]) in0[sccno[v]] = out0[sccno[u]] = 0;
 84             }
 85         }
 86 
 87         int a = 0, b = 0;
 88         for (int i = 1; i <= scc_cnt; i++)
 89         {
 90             if (in0[i]) a++;
 91             if (out0[i]) b++;
 92         }
 93 
 94         int ans = max(a, b);
 95         if (scc_cnt == 1) ans = 0;
 96         printf("%d\n", ans);
 97     }
 98 }
 99 
100 int main()
101 {
102     input();
103     return 0;
104 }
I(lihe)

 

F题:给定N和1到N的一个排列,问序列中存不存在3个元素的等差子序列,Pi1 - Pi2 = Pi2 - Pi3,i1<i2<i3。N《=10000,时限4s。

我和niuniu讨论了下F题,尝试了一下暴力枚举N^2,g++提交TLE,然后发现有60组case之多。

我查看了一下dongfang队的记录,他们代码长度816 B(我们的743 B),内存使用384 KB,也就是差不多20000W的int型,运行了3187ms。

我认定了他们是暴力水过的。

 

Orz,niuniu给出了一种枚举的优化方式,枚举公差d,缩小范围,总复杂度控制在10^9内。我balabala写完提交,TLE。此时,我们又陷入了深深的泥潭。

 

lh大仙的B题,大意是,有N个cat和M个dog,有P个人,每个人喜欢某个cat(dog)和讨厌某个dog(cat),如果去掉了他不喜欢的动物保留了喜欢的,那么他就会开心。问,去掉一些动物最多能使得多少人开心。

这出现在白书上最大匹配的练习题目,没有给出解法。lh大仙就咬住一定是最大匹配。

 

这时,niuniu在继续做F,也在读别的题目,我想了想B,也读了读其他几个题目。

 

B题,我们始终以cat和dog为对象建立二分图求最大匹配,陷入了深深的泥潭,不得正解。144分钟的时候,dongfang队过了B题,我们分明听到了他们的讨论,确实是和匹配有关。

Orz,他们此时4题秒杀我们2题。

 

我看了board,B\E\F是此时过得最多的题目。

【听niuniu说了E题】,大意是,给定N个圆,求去掉最多多少个圆,使得第1、2、3个圆还能连通,3<=N<=200。

我推了推E,建图之后无法建立费用流模型,也找不出平面上圆相交的特殊性质。

后来灵光一闪,最终的路径,肯定是Y字形,也就是只用枚举A、B、C的第一个交点D,然后分别D到A\B\C的最短路。

写了个Floyd,提交TLE。case数比较多?转用了dijkstra,178min FB。

 1 #include<stdio.h>
 2 #include<math.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 
 6 int n;
 7 struct cir{
 8     int x, y, r;
 9 }sq[222];
10 int mp[222][222];
11 int calc(int p, int q)
12 {
13     return ((sq[p].x - sq[q].x) * (sq[p].x - sq[q].x) + (sq[p].y - sq[q].y) * (sq[p].y - sq[q].y) <= (sq[p].r + sq[q].r)*(sq[p].r + sq[q].r));
14 }
15 int dis[4][222];
16 int vis[222];
17 void spfa(int S, int * f)
18 {
19     memset(vis, 0, sizeof(vis));
20     for (int i=1;i<=n;i++)
21         f[i] = 100000;
22     f[S] = 1;
23     for (int i=1;i<=n;i++)
24     {
25         int p = 1;
26         int mm = 100000;
27         for (int j=1;j<=n;j++)
28             if (!vis[j] && f[j]<mm){
29                 mm = f[j];
30                 p = j;
31             }
32         vis[p] = 1;
33         for (int j=1;j<=n;j++)
34             if(!vis[j] && mp[p][j] && f[p] + mp[p][j] < f[j])
35             {
36                 f[j] = f[p] + 1;
37             }
38     }
39     return ;
40 }
41 int solve()
42 {
43     int A = 1, B = 2, C = 3;
44     spfa(A,dis[A]);
45     spfa(B,dis[B]);
46     spfa(C,dis[C]);
47 
48     int res  = -1;
49     for (int d = 1;d<=n;d++)
50     {
51         if (dis[A][d]< 100000&& dis[B][d]!=100000 && dis[C][d]!=100000)
52         {
53             int tmp = dis[A][d] + dis[B][d] + dis[C][d] - 2;
54             if (res == -1 || tmp < res)
55             {
56                 res = tmp;
57             }
58         }
59     }
60     return res;
61 }
62 int main()
63 {
64     int cas;
65     scanf("%d",&cas);
66     while (cas--)
67     {
68         scanf("%d", &n);
69         for (int i=1;i<=n;i++)
70         {
71             scanf("%d%d%d", &sq[i].x, &sq[i].y, &sq[i].r);
72         }
73         for (int i=1;i<=n;i++)
74         {
75             for (int j=1;j<=n;j++)
76             {
77                 mp[i][j] = calc(i,j);
78             }
79         }
80         int ans = solve();
81         if (ans == -1)
82             printf("%d\n",ans);
83         else{
84             printf("%d\n", n - ans);
85         }
86     }
87     return 0;
88 }
E(wangsouc)

 

 

期间我读了D题,和niuniu讨论,此题是lcs的变形,我认为是可做的,让niuniu分析分析。

 

【然后我又继续YY F题】,我换用了C语法,使用C提交,居然AC了!时间2671ms,然后我把之前那个使用c++提交,也过了2671ms。235min,3A。

跪:G++、C++、GCC,在运行上确实差异很多,C++运行要快,G++读写快。

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 #define maxn 10005
 5 
 6 int seq[maxn];
 7 int hash[maxn];
 8 int n;
 9 bool calc()
10 {
11     int d, i,tmp = n;
12     for (d = 1;d<=n/2;d++)
13     {
14         tmp -= 2;
15         for (i=1;i<=tmp;i++)
16         {
17             if (hash[i] < hash[i+d] && hash[i+d] < hash[i+ d+ d])
18             {
19                 return true;
20             }
21             if (hash[i] > hash[i+d] && hash[i+d] > hash[i+ d+ d])
22             {
23                 return true;
24             }
25 
26         }
27     }
28     return false;
29 }
30 int main()
31 {
32     int T,i,x;
33     scanf("%d", &T);
34     while(T--)
35     {
36         scanf("%d", &n);
37         for(i = 1; i <= n; i++)
38         {
39             scanf("%d", &x);
40             hash[x] = i;
41         }
42         if (calc())
43             puts("Y");
44         else
45             puts("N");
46     }
47     return 0;
48 }
F(wangsouc + niuniu)

 

 

 

【B】然后lh大仙有想法要写B题,就交电脑给他coding。

居然不知不觉把B给过了,243min A掉。太神奇了有没有!!原来是对人进行建图。是个好题啊。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 #include <string.h>
 6 #include <string>
 7 
 8 using namespace std;
 9 
10 const int MAXN = 500 + 10;
11 int n, m, k;
12 int c[MAXN][MAXN];
13 bool vis[MAXN];
14 int match[MAXN];
15 
16 bool dfs(int u)
17 {
18     for (int i = 0; i < k; i++)
19     {
20         if (!vis[i] && c[u][i])
21         {
22             vis[i] = true;
23             if (match[i] == -1 || dfs(match[i]))
24             {
25                 match[i] = u;
26                 return true;
27             }
28         }
29     }
30 
31     return false;
32 }
33 
34 void solve()
35 {
36     int res = 0;
37 
38     for (int i = 0; i < k; i++)
39     {
40         memset(vis, false, sizeof(vis));
41         if (dfs(i))
42         {
43             res++;
44         }
45     }
46     printf("%d\n", k - res / 2);
47 }
48 
49 struct Node
50 {
51     string a, b;
52 }node[MAXN];
53 
54 void input()
55 {
56     while (scanf("%d %d %d", &n, &m, &k) != EOF)
57     {
58         int a, b;
59         memset(c, 0, sizeof(c));
60         memset(match, -1, sizeof(match));
61         for (int i = 0; i < k; i++)
62         {
63             cin >> node[i].a >> node[i].b;
64         }
65 
66         for (int i = 0; i < k; i++)
67         {
68             for (int j = 0; j < k; j++)
69             {
70                 if (node[i].a == node[j].b)
71                 {
72                     c[i][j] = c[j][i] = 1;
73                 }
74             }
75         }
76 
77         solve();
78     }
79 }
80 
81 int main()
82 {
83     input();
84     return 0;
85 }
B(lihe)

 

 

后面又和lh讨论了A题,大意,给定N<=16个数,进行二进制形式链接(重合部分可以重叠),求连接之后最小的串。我的第一直觉是TSP问题,不过那个最小值和后缀不好维护啊,现在我也不会。后面想想AC自动机维护后最,YY半天不会弄。

【转而搞D】,大意,给定A串和B串,进行操作:删除\插入\替换(编辑距离),然后是可以改变后缀如abcdefg变为abcddddd(显然倒序之后就是改变前序)。

 

和niuniu讨论了很久,标准的lcs模型,niuniu想不清楚公式:

f[i-1][j] + 1 ->f[i][j](删除第i个)

f[i][j-1] + 1 -> f[i][j](添加第j个)

f[i-1][j-1] + (A[i] != B[j])->f[i][j](不同就change)

估计是脑容量不够用了,一般比赛这个时候都是体力脑力精力透支啊!

 

我设计了空间和时间都是O(52*N*M),N、M<=500,的算法。大概算了算需要125*10^5个int型,第一反映是会MLE。没写。

最后20分钟,dongfang队走了,lh大仙也跟着走了,我和niuniu闲得没事就搜了搜,发现正解就开了52*N*N的数组。

我坚定的要写D,niuniu在一旁帮我看着(她这个时候应该已经理解转移公式了)

 

最后还剩下10min,我写完提交MLE,原来数组开成55*555*555了,我改掉成55*51*51提交WA。

后面才发现A串长度和B串不一样,改掉提交WA。

我知道f[k][i][j]也需要考虑前缀变换,于是加上提交,AC! 312min,5A。

太激动了有没有!

然后,我把比赛时间加了30min。掉人品啊!

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 const int maxn = 501;
  9 char str[maxn];
 10 const int inf = 0x3f3f3f3f;
 11 int A[maxn];
 12 int B[maxn];
 13 int n;
 14 int m;
 15 int dp[maxn][maxn];
 16 int f[53][maxn][maxn];
 17 int get_id(char ch)
 18 {
 19     if (ch<='Z' && ch>='A')
 20         return ch - 'A';
 21     return 26 + ch - 'a';
 22 }
 23 
 24 
 25 
 26 void init()
 27 {
 28     memset(f,-1, sizeof(f));
 29 
 30     for (int k=0;k<52;k++)
 31     {
 32         for (int i=0;i<maxn;i++)
 33         {
 34             f[k][0][i] = i;
 35             f[k][i][0] = i;
 36         }
 37     }
 38 
 39     for (int i=1;i<=n;i++)
 40     {
 41         for (int j=1;j<=m;j++)
 42         {
 43             for (int k=0;k<52;k++)
 44             {
 45                 f[k][i][j] = f[k][i-1][j] + 1;
 46                 f[k][i][j] = min(f[k][i][j], f[k][i-1][j-1] + (k != (int)B[j]));
 47                 f[k][i][j] = min(f[k][i][j], f[k][i][j-1] + 1);
 48                 f[k][i][j] = min(f[k][i][j], f[B[j]][i-1][j] + 1 + (k!=B[j]));
 49                 f[k][i][j] = min(f[k][i][j], f[B[j]][i-1][j-1]  + (k!=B[j]));
 50                 f[k][i][j] = min(f[k][i][j], f[B[j]][i][j-1] + 1 + (k!=B[j]));
 51             }
 52         }
 53     }
 54     return ;
 55 }
 56 int main()
 57 {
 58 //    printf("%d\n",get_id('Z'));
 59     while (scanf("%s",str))
 60     {
 61         if (str[0]=='#')
 62             break;
 63         n = strlen(str);
 64         for (int i=1;i<=n;i++)
 65         {
 66             A[i] = get_id(str[n - i]);
 67         }
 68         scanf("%s",str);
 69         m = strlen(str);
 70         for (int i=1;i<=m;i++)
 71         {
 72             B[i] = get_id(str[m-i]);
 73         }
 74 
 75         init();
 76 
 77 
 78         for (int i=0;i<=n;i++)
 79         {
 80             for (int j=0;j<=m;j++)
 81             {
 82                 dp[i][j] = inf;
 83             }
 84         }
 85 
 86         for (int i=0;i<maxn;i++)
 87         {
 88             dp[0][i] = i;
 89             dp[i][0] = i;
 90         }
 91         for (int i=1;i<=n;i++)
 92         {
 93             for (int j=1;j<=m;j++)
 94             {
 95                 dp[i][j] = dp[i-1][j] + 1;
 96                 dp[i][j] = min(dp[i][j], dp[i][j-1] + 1);
 97                 dp[i][j] = min(dp[i][j], dp[i-1][j-1] + (A[i] != B[j]));
 98                 int tmp = inf;
 99                 for (int k=0;k<52;k++)
100                 {
101                     tmp = min(tmp, 1 + f[k][i][j]);
102                 }
103                 dp[i][j] = min(dp[i][j], tmp);
104             }
105         }
106         printf("%d\n",dp[n][m]);
107     }
108     return 0;
109 }
D(wangsouc+niuniu)

 

 

总结:

0、我和niuniu迟到近50min,是绝对错误的,以后的比赛,不会再迟到。

1、lh大仙深深的陷入了B题,拉住了全场。I题虽过,掉人品的。

2、所有题目还属于比较轻松的,English要求也不高,我读了其中的B\C\D\F\H\I,其中A\C题没读懂,所有题目都被读了。但是,C\G没有讨论。

3、题目难度属于中等偏下的难度,和省赛难度差不多,多校训练里算最简单的了。

4、目前组队比赛,分工还不明确,讨论不够,比如(lh和niuniu经常都没讨论),而我基本要和两个都讨论;这点,需要加大知识面的交集和题目阅读的交集。

5、niuniu编码能力有待提高,应该有做到自己的算法自己能实现,特别是水题。

6、在图论、DP方面,3个人都应该要多学学,这样才会有讨论的交集,很重要!

7、以后下来还是要多下来讨论总结。

加油!

转载于:https://www.cnblogs.com/wangsouc/articles/3691904.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Mirror是一种非常有用的组队工具,它允许多个玩家共享和交互的游戏世界。无论是开发多人在线游戏、合作游戏还是竞技游戏,Unity Mirror都能提供强大的网络功能。 借助Unity Mirror,我们可以轻松地创建一个支持多人游戏的环境。无论是局域网还是互联网,Unity Mirror都能提供稳定的网络连接,并且具备较低的延迟。这使得玩家可以流畅地与其他玩家一起玩游戏,共同完成任务或对战。 Unity Mirror还提供了丰富的同步功能,如角色同步、物体同步和动画同步等等。这些功能确保了游戏中的所有玩家都能看到并与同一游戏世界进行互动。无论玩家在哪个地点,都能感受到与其他玩家的实时互动。 在组队方面,Unity Mirror提供了简便的方式来创建和管理队伍。我们可以很容易地将玩家分配到不同的队伍,并且提供相应的组队功能。例如,我们可以实现队伍内成员之间的实时通讯,协同作战和分享资源等等。 通过Unity Mirror,我们可以创建一个灵活且强大的多人游戏体验。无论是与好友合作还是与陌生人对战,多人游戏的乐趣将大大增加。Unity Mirror的出色网络功能和组队管理能力,使得游戏开发者能够设计出更具互动性和社交性的游戏。 总之,Unity Mirror是一个非常适合组队游戏的工具,它提供了可靠的网络连接、实时的同步功能以及便捷的组队管理。无论是作为游戏开发者还是玩家,我们都可以享受到Unity Mirror带来的多人游戏乐趣。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值