各种训练赛小结

Contest #1    CQ Round 1  (巴蜀命题)      2016/10/25

Rank: 19    Score : 140

从现在开始每场训练赛尽量写一点总结吧,开始的有点晚,但是还有十几场吧。

这场比赛题目难度一般,比较分散。

暂时不讨论因为没有学2—set而爆〇的T2,本次的T1还是有亮点的:

60分没拿到的可以回家种田了。

正解的搜索感觉技巧性很强,但还是有大神想到。

一上来就觉得本题可以分段打表,事实上的确如此。可惜暴力功底不够,花了70分钟左右只搞出两个概率较高的答案,居然两个答案都中,运气爆炸。看唯一AC的大神代码,也不过多打了一点表。暴力功夫有待提高啊。

代码里面有一个细节问题:

const int maxn=100000+5;
int cnt[maxn];
for(int i=1;i<maxn;i++)cnt[i]=1;

申明数组的时候是cnt[maxn],实际上cnt[maxn]指向一个随机的位置,恰好这样就会WA掉第一组小数据(出题人真不错,这都能坑)。所以以后maxn做循环控制变量一定不能取等。


T3上来10分钟直接打完了暴力,但是LCA有点小错,浪费了30分钟以上,最后分析了一半。。。亏的一匹。


Contest #2   CQ Round 2  (一中命题)      2016/10/26

Rank: 4      Score : 294

唯一没AC的居然是第一题?!(LZ的诅咒)

没必要的上限就不要乱搞了,否则WA爆。

这次的T2是原题,T3一般,总之比上次水多了。


Conteset # 3  CQ Round 3 (南开)

Rank: ???   Score: 195

第一题杨辉三角找规律,找的很快,但是写了很久。递推除法在模余系下要用逆元,居然对拍了40分钟才看出来。最后还因为数组爆炸丢了5分。只要不超过限制,数组一定开够啊!

第二题 Trie +DP ,20分钟秒杀,然而只有50分(一行代码啊啊啊,亏的一匹)。写完代码后一定要读一遍再去测样例,否则过了样例容易掉以轻心,没过影响心情。

第三题 50骗分程序达到了预期,正解确实不好想到。


Conteset# 4 CQ Round 4 (八中)

Rank: 12      Score: 180

第一题虽然找到了规律,还是超鬼了。以后这种题暴力写得快一定要打出表来,便于观察。80分是因为超出了unsigned long long ,还有一个简单的特判。以后这种找规律的数学题要注意以下几点:

1>注意数据范围,有些细节用不同的写法可能就不会超long long

举个栗子:

// 求不超过n的  m 的 幂

//   Code #1  
    unsigned  long long M=1;
    while(M<=n)M*=m;    
    M/=m;
    
//   Code #2
     unsigned long long M=1;
     while(n/M>=m)M*=m;
     
//    Code #3
     unsigned long long M=1;
	 M=floor(log(n)/log(m));
	 M=Pow(m,M);  //快速幂
	      
/* 
	容易发现Code #1 多乘了一次,所以用可能会爆炸。 
	Code #2 和 Code #3都不会爆炸, Code #3还可以用快速幂。
*/ 


2> 注意是否有特判,这很容易忽略,对拍的时候 特殊数据和 极限数据 都要注意到。

3> 答案是否需要模,如果有,注意使用乘法逆元


第二题挺水的,秒杀,不多说。

第三题离散化+堆+贪心。

  这类题真的不好想,可以从以下几个方面入手:

        (1) 局部最优+适当改悔==全局最优

        (2) 按顺序讨论某些变量,可能会带来更多的贪心结论。

        (3) 合理利用堆和其他数据结构的性质


Conteset #5 XSFZ VS NK Round 6

 Rank: 8 

活活把Rank 1丢啦!亏得一匹。

第一题:简单的搜索,不说了。

第二题: 问题转化后:区间DP。

                接下来问题来了,一个小地方没有写Sort,30分没有了.

                以后最后的几分钟一定要读一读自己的代码!!!

第三题:


Contest #6 CQ Round 5(巴蜀)

Rank: 18   Score: 100

第一题这一次还算正常,一个小时A掉,代码想的有点久,水题。

第二题树形DP,想到了,但是状态没有定对,爆搜30分没有拿到应该好好反省,这种题写搜索一定保证在半个小时以内写完写对,小分到手。 暴力功夫不够?

第三题 本来完全想对了90分算法,可是由于两个小错误,WA成0分!细节决定成败啊!

     错误1:本来是想图方便,炫炫技,结果反被数据秀了一波。

   将两个0到N的数压成一个数的写法 应该是 a*(N+1)+b。注意一定是(N+1)!!

         错误2:LCA经典错误(错了几次,没引起重视,终于炸了)

//正确的LCA 
int LCA(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    int i,p=dep[x]-dep[y];
    for(i=0;i<=S;i++)
       if((p>>i)&1)x=fa[x][i];
    if(x==y) return x;
    /*
		注意,这里的k一定不能用倍增上限S代替,否则会导致fa[x][i]在i>k时指向无意义的节点,导致wa
		其他地方都可以用S
	*/ 
    int k=ceil(log(dep[x])/log(2));   
	for(i=k;i>=0;i--)
		if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}

Contest #7 CQ Round 6(一中)

Rank:10 Score: 190

第一题贪心,数据很水,比较暴力的方法也能过,但是贪心原则想了一个小时左右,耗是太久,导致最后一题的搜索都没写完。

第二题: 最短路重新建图+DP

    本场比赛的送分题,90分是数据的问题,超过范围了。数组在不超过限制的情况下尽量开大。下面以256MB的内存限制为例,列举一些极限(实际占用大概220MB):

        256MB= 58000000个int =29000000个LONG LONG=23200000000个bool 

第三题:暴力的搜索裸题

剪枝都想到了,时间不够了,代码没写出来,想到了好的剪枝,不要怕代码难写,能得分就行。


互测赛改悔:

多组数据不要乱用return 0...算出一个答案就愉快的return 0了,于是WA了90分


Contest #8 2015 CQ Round ?

Rank:? Score: 150

第一题 暴力,不说了。

第二题Hash,玄学算法,注意两点:

  (1)一个哈希冲突可能性有点大,不妨用两个。

  (2)连续子串的Hash不用重复计算,是可以O(1)转移的。

    (3)计算Hash值的时候不要乱取模(这个很容易错)。

第三题

       爆搜拿到了暴力分,其实正解是动规。

       第一反应认为有后效性,其实化简之后是没有后效性的,坑啊!

       形如F[n]的函数,如果只是和N有关的多项式,可以和数列一样退下标得到递推式。

      戳这里


Contest #9 2016 CQ Round  7 (By nodgd)

Rank & Score: 不可描述

被Nodgd支配的恐惧!!

第一题: 组合数学

在第一个简单问题上时间花的太多,凡是关于组合数学的题,先在草稿本上把杨辉三角画出来肯定是没错的,非常有利于快速找到规律。还有要对一些组合数学的模型熟悉比如这次涉及到一个隔板原理:

        将n个小球分成m组的方案数为C(n-1,m-1)。

      证明:考虑将n个球排成一排,在n-1个空隙中插入m-1个隔板,即分成了m组,故方案数为C(n-1,m-1)。

     题目链接 :A


第二题: 线段树+变态Lazy标记

这道题确实非常巧妙,主要体现的是对线段树Lazy标记非常深刻到位的理解。

lazy标记是用来干什么的? 传递修改操作 ,通过标记区间来降低修改的时间复杂度

首先看到这个题想到了一个经典的题:

维护一个序列,支持以下三种操作:

①Add(L,R,V) 将 [L,R]这段区间的值增加V

②Set(L,R,V) 将  [L,R] 这段区间的值设置成V

③Query(L,R) 查询L,R区间的最大值

这道题的实现用了两个Lazy标记,pushdown(传递标记)的时候采用的是先考虑Set,再考虑Add,

update的时候 对于set先清除Add标记,对于Add则不用清除set标记。


为什么这个题不能照搬,用两个Lazy呢?

上题中,Set和Add两个标记虽然看起来是独立的,但我们注意的那些(比如先考虑Set,再考虑Add),其实就是找到了两种操作的一种联系,体现到了标记的处理上,实际上这两个标记是一个整体,并不互相独立。而处理标记的关键在于如何叠加标记:

比如add标记的叠加非常简单,直接加上一个值就行。这个题同样,要找到两种操作之间的联系,通过数学上的划归,最后发现必须使用三元组(a,b,c)标记才能转移下去。

所以不管多少个标记,他们都该是统一的,可以转移的,总之Lazy的核心就是 转移。


Contest #10   2016CQ Round 8 (by 八中)

Rank: 12    Score: 200

这场为什么我骗分这么厉害? 

第一题: 一下想到了贪心,写了一下,过了样例,手出了几组错数据居然也过了,于是开开心心的交了,还好这题贪心比较厉害,可以骗80分。

正解 DP,为什么当时没想一想? 至少应该写一下状态吧,这题很容易看出来。

第二题: 单调队列  确实没看出来,写了个二维的RMQ,其实这题一维RMQ每行开一个就行了,感觉以后有点用,贴在这里。

拿到一个无法入手的问题怎么办? 从简单的情况入手!

如果是一维的,怎么做? 对于x找出左边能延伸到的L[x],右边能延伸到的R[x]-----广告牌模型!

所以枚举第i行到第j行,求出min[k]  (第i行到第j行第k列的最小值),把二维的矩阵变成一维的,再用一个单调队列就行了。

二维RMQ代码:

const int maxn=300+5,inf=0x3f3f3f3f;

int n,m,s[maxn][maxn],f[maxn][10][maxn][10];

int RMQ(int x1,int y1,int x2,int y2){
	int k=0,t=0;
	while((1<<(k+1))<=x2-x1+1)k++;
	while((1<<(t+1))<=y2-y1+1)t++;
	int Min=f[x1][k][y1][t];
	Min=min(Min,f[x1][k][y2-(1<<t)+1][t]);
	Min=min(Min,f[x2-(1<<k)+1][k][y1][t]);
	Min=min(Min,f[x2-(1<<k)+1][k][y2-(1<<t)+1][t]);
	return Min;
}

int main(){
	int i,j,k,p;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)scanf("%d",&s[i][j]);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)f[i][0][j][0]=s[i][j];
	for(i=1;i<=n;i++)
		for(j=1;(1<<j)<=m+1;j++)
			for(k=1;k+(1<<j)-1<=m;k++)
				f[i][0][k][j]=min(f[i][0][k][j-1],f[i][0][k+(1<<(j-1))][j-1]);
	for(i=1;i<=m;i++)
		for(j=1;(1<<j)<=n+1;j++)
			for(k=1;k+(1<<j)-1<=n;k++)
				f[k][j][i][0]=min(f[k][j-1][i][0],f[k+(1<<(j-1))][j-1][i][0]);
	for(k=1;(1<<k)<=n+1;k++)
		for(p=1;(1<<p)<=m+1;p++)
			for(i=1;i+(1<<k)-1<=n;i++)
				for(j=1;j+(1<<p)-1<=m;j++){
					int& x=f[i][k][j][p]; 
					x=f[i][k-1][j][p-1];
					x=min(x,f[i][k-1][j+(1<<(p-1))][p-1]);
					x=min(x,f[i+(1<<(k-1))][k-1][j][p-1]);
					x=min(x,f[i+(1<<(k-1))][k-1][j+(1<<(p-1))][p-1]);
				}
	return 0;
}
第三题 是辗转相除法的运用,就是眼瞎,永远看不出来,但是由于题目本身导致答案简单,骗分骗了90分,还行吧。


 小小的改悔: 使用unique之前先排序!!!!!!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值