zoukankan      html  css  js  c++  java
  • 4.29模拟赛赛后总结

    4.29模拟赛赛后总结

    比赛历程

    早上睡醒已经是AM7:20,洗漱过后来到机房说要换题,也就是说开始的时间和大家没有差别,大约AM7:45开始看题。

    AM8:00 好像才看了一遍题,想着这次一定要先把暴力打完。

    分析了一波T1,感觉暴力可过的分挺多的,好像暴力就有(O(qm))的复杂度了,于是开始打暴力。

    AM8:35打完调完了暴力,看了一眼T2,脑海中大概过了一下题目的意思,然后去了躺厕所。

    去厕所的时候想到了T1好像可以进行一些优化,暴力的找所有路径太暴力了,应该想怎么能够一次统计多条路径。

    想到这个图似乎是个拓扑图(这个时候没有注意到(ai<bi)) 所以按照度数拍一下序,然后从先的点开始跑,根据dep统计一个边产生的贡献,并且这个贡献可不是乱给的,如果两个点能够到达同一个点,那么这个dep就得在其中一个起点出发的路径上断掉,dep就不必再加深。

    当然当时的思路没有这么顺畅,不过总归是梳理好了,在大概9:10的时候打出来了代码,然后开始我Linux下的第一次对拍。

    结果很扯的事情出现了,虽然我想着dep加深的过程中是一个等差数列,能够(O(n))的统计答案为(n^2)的路径,但是随机数据下竟然有时候还没有暴力快。。

    感觉有点自闭,好像是白搞了一样,不过正式的数据这个优化应该会有优势。

    然后开始看T2,思前想后,以为m<=3有搞头,但是并不会容斥掉这个东西。。结果在AM10:30的时候只有一个暴力可以搞。

    AM:10:40 接受现实并开始思考T3,今天的暴力时间好在比较充足,T3这个十分的小暴力模拟起来还挺费劲(其实就两个dfs)

    AM:11:00,打完调完暴力思考后边的分数,感觉这个序列的数据可以分块,大概思考了一下如何维护块的信息,感觉可行,于是就开始码了。

    开始码的时间大概要AM:11:20,框架刚出来就已经是AM11:30了,不过老师说要延长30分钟,还好。

    AM11:50码完发现好个锤子,手造数据过不去,细节有问题,自闭了。

    虽然大家都说只有暴力分

    赛后发现&思考

    1 人均得分60+30+10. 前6都是,但是我是40+30+10,不知为何,我T1 TLE了两个点,找原因未果。

    2 T3链的数据确实可以分块,赛后又调了好大会儿。一开始发现有一个地方算错了块的边界,"blo*(id-1)+1"写成了“(blo-1) *id+1”.. 后来发现还有边界没有特判,再后来发现change的地方对于单点的判断忘记了异或懒标记。。。改完最后一个地方之后终于过了。以为正解也能够树分块。但是发现询问是一个发散的而不是针对链的。自闭了。

    3 老师说T3是线段树二分套路,虽然我第一反应是分块。然后因为我们明明练过这个东西却仍然不会,我们又多了个专题作业。 感觉确实是这样,怎么学的没有忘的快呢。大概还是理解不够深刻,还有一点就是练习不够多。

    4 学过的套路不会->复习->订题订不完->新东西没搞会->又遇到了然后不会->补->。。。。

    由于这样一个传递关系,基本上一个东西遇到两三次才能够学会,而有的东西因为只遇到过一次,可能就没机会会了。而且由于要干的事情太多了,感到并没有做什么时间就过去了。接下来要考虑理清楚事情的顺序,安排一个优先级,分个必要和非必要,慢慢提高自己的熟练度和效率吧。如果东张西望,或者草草了事,那我感觉能干的事情只会更少,而未来能干的事情也会越来越少。

    技术总结

    T1 正解是DP,转移其实类似dfs的过程,然后可以通过比较度数来考虑dp转移是推还是拉,以此来做到dp记录的不重不漏,而由于题目中给出的条件,(a_i<b_i),每次读入的点进行排序之后可以从小到大枚举,然后顺次利用度数小的dp值来更新自己,然后自己更新度数大的,这样可以做到不重不漏,而且这样的一层枚举可以证明复杂度是(sqrt{m}) 的,这样最终的复杂度就是(O(Msqrt{m}))的。

    T2 正解暂时不会。

    T3正解暂时不会。但是这里需要讨论一下这道题的部分分,即第2和第3个点,用分块做思路确实不难,但是细节上需要一段时间的调试,而线段树二分就不一样了,线段树二分模式比较固定,更新方式类似分块,但是查询采用二分,可以向左向右二分最大值或者说二分区间和,直到区间和为0。

    其实线段树二分比一般的二分还要简单,毕竟线段树的结构比较固定,简单的跳儿子就可以了。其实线段树二分实现的复杂不在于二分,而在于区间信息的维护。

    以sinao这道题为例,线段树二分的代码是这样的:

    int find(int cnt,int l,int r,ll val){//寻找最左 
    	if(l==r) return tr[cnt].sum<val?n+1:l;//如果说,最终没有割,返回n+1
    	psd(cnt,l,r);
    	if(tr[ls].mx>=val) return find(ls,l,mid,val);
    	else return find(rs,mid+1,r,val); 
    }
    

    这个难吗?显然不难.比一般的二分要考虑的东西还要少。这道题麻烦的在于信息更新的顺序。T3链的部分分也是类似的。
    难的都不是板子,而是思想的灵活应用。

    还有一道例题是脑洞治疗仪
    find的方式是不太一样的,利用一般形式的二分查找。

    int find(int l,int r,int brain){
    	while(l<r){
    		int x=qhole(1,1,n,l,mid);
    		if(brain>x) l=mid+1,brain-=x;
    		else r=mid;
    	}
    	return l;
    }
    

    这个写法的一个变形是这样的

    int find(int L,int R,int brain){
    	int l=L,r=R+1;
    	while(l+1<r){
    		int x=qhole(1,1,n,L,mid);
    		if(x<=brain) l=mid;
    		else r=mid;
    	}
    	return l;
    }
    

    二者是(log_2^2n)的一个二分查找,前者则减去之后到另一个区间查找剩余,这个查找剩余的写法在平衡树里边比较常见,而最近才学了平衡树,于是现在比较喜欢这样写,后者是从最开始的询问L直接找到值的位置,这个变形是题解里的写法,殊途同归。

  • 相关阅读:
    在GridView中绑定HyperLink
    C语言学习之我见strcat()字符拼接函数(有缺陷)
    C语言学习之我见strcmp()字符串比较函数
    C语言学习之我见memchr()内存查找字符函数
    C语言学习之我见strncmp()字符串比较函数(控制范围)
    C语言学习之我见strncat()可调整的字符串拼接函数
    C语言学习之我见strlen()字符串长度函数
    设计高并发的电子商店
    实战业务逻辑层
    实战架构设计
  • 原文地址:https://www.cnblogs.com/mikuo/p/14720362.html
Copyright © 2011-2022 走看看