【题解】牛客CSP-S提高组赛前集训营5

A-无形的博弈

暴力做法

枚举每个状态。暴力搜索。

100分

输出。证明如下:

对于一个串,设有一个指针初始指向0,那么往右旋转就是指针往右移。每次操作这个指针指向的数。

神J的策略如下:

定义一轮为这个指针走完一圈,那么在每一轮里,

神J每次能变成0就变成0,如果神树大人把一个0变成1了那么在这一轮内什么都不做。

发现若把这个串视作一个二进制数那么这个二进制数一定在增加。

所以对于所有串都是神J必胜。

B-十二桥问题

24分
注意到有,直接一遍最短路跑过去跑回来即可。

40-70分
为了获得更多的分数,一个很朴实的想法是定义状态为(当前位置,访问过的大桥),即定义数组dist[pos][status]的意义为当前在位置pos,利用二进制状压维护status。通过最短路可以直接跑出答案,大概可以获得分。

100分
正解也很容易想到,我们注意到条边相连的点,再加上起点是最重要的点了,其他的点都无关紧要。我们可以想办法建立一张只有这个点的小图,然后跑上述状压方法的最短路得到答案。

构造这张小图,最简单的方法当然是基于这个点分别跑一遍最短路。其实只要跑次最短路就好了。

具体的构造方法是在这个小图中,先连接所有大桥。然后对于其中任意两点都通过在原图上跑最短路的方法得到距离(不用考虑是否经过大桥),并在小图上连接。然后用类似旅行商问题的方法(只是这次变成了经过某些边时改变状态)直接跑即可。

总时间复杂度

p.s: 卡SPFA的数据是利用CYaRon构造的。

C-神J上树

30分

使用Floyd,复杂度为

100分

路径只能是从上往下走。可以发现从s到t途中经过的点的编号一定是一个单调递减的序列。

接下来的问题就是如何快速算这个序列了。

考虑树剖,把问题转化为个在序列上的问题。在序列上,这个问题可以用单调栈解决。

所以将询问离线(在线也可以),然后对于每条重链用单调栈从下到上扫一遍。复杂度。标程写的,不过常数非常小。

如果只实现序列上的问题可以得到70分。

不要再问我是谁了。

A的标程:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41725858&scrollToDetail=1
B的标程:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41736673&scrollToDetail=1
C的标程:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41725752&scrollToDetail=1

全部评论
首先定义指针循环一遍为一轮,一轮中J和T(树)会总共操作n次。 最终J胜利必是全1或全0 考虑J的最优操作方式,J如果想要全1胜利,J无法使0变成1,则T也会选择不操作跟J耗着,这样就会死循环,因此J必须操作将1变为0来逼迫T操作,此时全0成为J的目标,T必然不会满足他的目标于是会操作一波,但是T将0变为1后,当前一轮就不能全0了,(注意是当前一轮,J不能操作已经操作过的数),所以J改变策略(与其说改变不如说J一开始就是要全1胜利,把1变成0只是J逼迫T操作的阴谋),此轮剩下未操作的1都不操作了,这样一来,以序列的从左向右分别作为二进制数的第1、第2位的话,这个二进制数一定是增大的。 证明为什么增大:这个就比较好证明了,众所周知2^i>2^i-1+2^i-2....而每一轮序列分别是从左向右也就是位数逐渐增大的操作,虽然前面J将1变成了0,但是只要后面出现了0变为1就肯定能把之前的二进制损失的数所弥补回来,而且之后也不会有二进制损失了。 (以上仅个人理解,错误麻烦告知,谢啦😀)
23 回复
分享
发布于 2019-11-08 10:13
只有我觉得T1的题解很不清楚吗???
8 回复
分享
发布于 2019-11-08 07:27
阅文集团
校招火热招聘中
官网直投
请问T3两条路径出题人怎么O(1)合并的?
6 回复
分享
发布于 2019-11-08 07:56
所以同机房一堆巨佬SPFA过T2。。。。。。
5 回复
分享
发布于 2019-11-07 23:10
十年OI一场空,不开longlong见祖宗🙃T1 60pts祭
4 回复
分享
发布于 2019-11-08 08:42
S!!!T!!!D!!!
3 回复
分享
发布于 2019-11-08 16:54
想知道为什么T2的#2能卡掉分层图。。还是说只是我写丑了
2 回复
分享
发布于 2019-11-07 22:54
请问标算在哪里
2 回复
分享
发布于 2019-11-08 08:39
T2为什么跑13遍最短路即可???
2 回复
分享
发布于 2019-11-08 11:59
T2可以折半搜索吗?
1 回复
分享
发布于 2019-11-07 23:39
@溴溴溴 时间复杂度不是2个log的吗,对于每一个询问,需要把每一个重链提出来,然后在单调栈上面二分
1 回复
分享
发布于 2019-11-08 07:19
T3两个log貌似也能过。。
1 回复
分享
发布于 2019-11-08 07:40
T3怎么用单调栈维护? 而且怎么把多条链的信息O(1)维护?
1 回复
分享
发布于 2019-11-08 08:31
@溴溴溴 大佬能再详细的讲一讲T1吗 话说回来二进制数不是在减少吗
1 回复
分享
发布于 2019-11-08 09:12
有大佬能告诉我T3的链是什么意思吗?这样的图也算一条链吗?
1 回复
分享
发布于 2019-11-08 09:53
- T1爆搜 #include <bits/stdc++.h> using namespace std; #define maxn 100 #define maxm 5600 int n; bool vis[maxm]; inline int read_() { int x_=0,f_=1;char c_=getchar(); while(c_<'0'||c_>'9') {if(c_=='-') f_=-1;c_=getchar();} while(c_>='0'&&c_<='9') {x_=(x_<<1)+(x_<<3)+c_-'0';c_=getchar();} return x_*f_; } bool dfs_(int S) { if( !S ) return true; if( vis[S] ) return false; int u = S & 1,pdc; if( u == 1 ) { // 变为0 pdc = S >> 1; vis[S] = true; if( dfs_(pdc) ) { vis[S] = false;return true;} vis[S] = false; // 不变 pdc = ( S >> 1 ) + ( 1 << ( n - 1 ) ); vis[S] = true; if( dfs_(pdc) ) { vis[S] = false;return true;} vis[S] = false; } else { // 变为1  pdc = ( S >> 1 ) + ( 1 << ( n - 1 ) ); vis[S] = true; bool flag = dfs_(pdc); vis[S] = false; // 不变 pdc = ( S >> 1 ); vis[S] = true; if( flag && dfs_(pdc) ) { vis[S] = false;return true;} vis[S] = false; } return false; }  int main() { //freopen("a.txt","r",stdin); scanf("%d",&n); int AKIOI = 0; for(int S = 0;S < ( 1 << n );++S) { memset(vis,false,sizeof(vis)); if( dfs_(S) ) ++AKIOI; } printf("%d",AKIOI); return 0; }
1 回复
分享
发布于 2019-11-08 11:23
T2能不能直接在原图上面跑13个最短路(个人感觉没啥区别)
1 回复
分享
发布于 2019-11-09 10:42
t3没说数据随机的情况下...用倍增依次查询最小值的方法可以过大部分点...不应该是每组数据都可以构造一条单调递减的树链然后去卡嘛....(本想着一小时创造奇迹...结果正解思路莽复杂了...暴力分都没拿到QAQ...回头看倍增的写法分那么高...心痛)
点赞 回复
分享
发布于 2019-11-07 23:18
T1的策略是n次一循环,神J优先把1变成0,直到神树把0变成1,身后这一循环内就不再变了吗?
点赞 回复
分享
发布于 2019-11-07 23:20
毒瘤出题人卡SPFA QAQ
点赞 回复
分享
发布于 2019-11-08 07:29

相关推荐

22 1 评论
分享
牛客网
牛客企业服务