一、队伍训练情况
浙大校赛网络同步赛,5题。
二、个人训练情况
Codeforces Round #551 (Div. 2)
2050编程竞赛
4+3+5还是只能做一些非dp的思维题。
三、遇到的问题&可行的解决方案
掌握的知识太少。
无解,能力有限,近几周需要加强学习,竞赛仅作基础训练。
浙大校赛网络同步赛,5题。
Codeforces Round #551 (Div. 2)
2050编程竞赛
4+3+5还是只能做一些非dp的思维题。
掌握的知识太少。
无解,能力有限,近几周需要加强学习,竞赛仅作基础训练。
计划下周开始到实验室训练
计蒜客ACM训练联盟周赛第二场
CodeforcesCodeforces Global Round 2
51Nod
止步于简单题
目标是什么?正在解决。
no response
刷了PTA和51Nod的一些题。
开学比赛状况不是很理想,之后自己刷了一些题。后面蓝桥杯省一,天梯赛151,尚可,需要准备蓝桥杯国赛和江苏省省赛。
第一,开学以来刷题疯狂减少,第一二周刷了几十道题,但这几周几乎没怎么刷题。解决方案为重新规划日常安排。
第二,开学后的几场比赛可能对心态有影响。要意识到这些比赛能够打出成绩是由于大部分题是简单的模拟,而自己对于很多算法还没有掌握,这些比赛并不能说明自己的水平。
在日常规划方面,抽出时间来学习算法和做题,一到两周后准备队伍的磨合和训练。
1、long long=int*int,会数据溢出,直接定义long long或者long long*=long long。(51Nod 1082)
2、不要再忘记题目条件了!输出No Solution!!!!(51Nod 1090)
3、二分答案可以在修改边界的过程中留一个ans=mid,要向上取整可以(n+mod-1)%mod,注意不要除以0。(POJ3104)
4、别人的程序初始化要看清楚。。。(POJ2976)
5、变量的重名问题!!!
6、重新检查题意!
7、不要偷懒,例如输入两个-1结束,就去判两个-1。
8、有时需要考虑给的数据是否满足前一个小于后一个,题目中不说可能不满足。
9、贪心和二分的正确性,有点玄学。
10、多组输入注意不要提前break掉,开平方不要开复数。(POJ1328)
11、注意修改变量的顺序!!!比如去掉最大公约数要先提取到一个变量,不能两次调用函数!!!
12、循环i套i。
update: 太傻了,不更新了,反正也不太会回来看,刷点题睡个好觉状态就有了。
俗称马拉车算法->_->
处理最长回文字串复杂度O(n)
这里菜鸡不会证,简单说一下思路。
由于回文串有奇有偶,所以将串之间和两边加上'#',为了防止后面某个地方超边界,新串0位置加上$。这样每个回文子串为#a#b#a#形式,必定奇数个,且原子串长度为新字串半径减一,求这个半径p[i]。(即p[i]是以i为中心的最长回文字串的半径)
i从1到n,过程中维护一个id点(id<i,i拉着id走,马拉车),它是某个回文子串的中心,这个字串右边界是当前最大的。(p[i]是半径,故i+p[i]为边界)
那么当右边界比i还大时,就可以根据对称性,找到i关于id的对称点j=2*id-i,来优化找字串的过程。怎么优化呢?在id管辖范围内,p[i]和p[j]情况是相同的。由于超出id右边界的的地方不符合对称性,因此p[i]=p[j]当且仅当p[j]小于等于j-(id-p[id])(即j串的左边界不超出id串的左边界),否则只能直接到id右边界,p[i]=mx-i,之后的手动算。
如果id右边界太小,不能做优化,也得手动算。
以下代码:
1 | #include<iostream> |
一、归并排序
递归思路,将一个序列二分,使前半段有序,使后半段有序,然后使用双指针扫一遍使整段有序。
对于n个元素,每个元素都在排序1个元素,2个元素,4个元素,8个元素......的时候出现,因此复杂度是O(nlogn)。
二、求逆序数
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
输出逆序数
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:
abcicba
abdkscab
ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
第1行:字符串A
第2行:字符串B
(A,B的长度 <= 1000)
输出最长的子序列,如果有多个,随意输出1个。
终于下定决心不碰运气写二分了。。。
思路比较乱,建议直接点进参考①
来说一下我记忆的方法
注意left<=right
首先标准查找是随机的找到一个,分三类,找不到返回-1
然后如果要找第一个和最后一个,因为是准确查找,所以要有判别和找不到返回-1
里面的大于还是大于等于,要具体分析。(分析相等的时候向左找还是向右找,返回谁)
举个例子
寻找最后一个相等的,没有的话找比key小的最后一个(searchLastEqualOrSmaller)
这两个元素的位置都是偏右(比如说{1,2,3,4,4,4,5,6},分成1,2,3|4,4,4|5,6,3和最后一个4都在所在区间的右边),因此要向右找,让相等的情况跟着缩小左边界,因此是大于
解释一下为什么返回right,根据while结束条件,最后right<right,如果没有相等的,arr[right]<key<arr[left],否则,key==arr[right]<arr[left](所以返回left就是比key大的第一个)
大于等于同理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
1 //递增
2 #include<cstdio>
3 #include<iostream>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 int search(int *arr,int n,int key){
8 int left=0,right=n-1;
9 while(left<=right){
10 int mid=(left+right)>>1;
11 if(arr[mid]==key) return mid;
12 else if(arr[mid]>key) right=mid-1;
13 else left=mid+1;
14 }
15 return -1;
16 }
17 int searchFirstEqual(int *arr,int n,int key){
18 int left=0,right=n-1;
19 while(left<=right){
20 int mid=(left+right)>>1;
21 if(arr[mid]>=key) right=mid-1;
22 else left=mid+1;
23 }
24 if(left<n&&arr[left]==key){
25 return left;
26 }
27 return -1;
28 }
29 int searchLastEqual(int *arr,int n,int key){
30 int left=0,right=n-1;
31 while(left<=right){
32 int mid=(left+right)>>1;
33 if(arr[mid]>key) right=mid-1;
34 else left=mid+1;
35 }
36 if(right>=0&&arr[right]==key){
37 return right;
38 }
39 return -1;
40 }
41 int searchLastEqualOrSmaller(int *arr,int n,int key){
42 int left=0,right=n-1;
43 while(left<=right){
44 int mid=(left+right)>>1;
45 if(arr[mid]>key) right=mid-1;
46 else left=mid+1;
47 }
48 return right;
49 }
50 int searchLastSmaller(int *arr,int n,int key){
51 int left=0,right=n-1;
52 while(left<=right){
53 int mid=(left+right)>>1;
54 if(arr[mid]>=key) right=mid-1;
55 else left=mid+1;
56 }
57 return right;
58 }
59 int searchFirstEqualOrLarger(int *arr,int n,int key){
60 int left=0,right=n-1;
61 while(left<=right){
62 int mid=(left+right)>>1;
63 if(arr[mid]>=key) right=mid-1;
64 else left=mid+1;
65 }
66 return left;
67 }
68 int searchFirstLarger(int *arr,int n,int key){
69 int left=0,right=n-1;
70 while(left<=right){
71 int mid=(left+right)>>1;
72 if(arr[mid]>key) right=mid-1;
73 else left=mid+1;
74 }
75 return left;
76 }
77
78 int main(){
79 int arr[17] = {1,
80 2, 2, 5, 5, 5,
81 5, 5, 5, 5, 5,
82 5, 5, 6, 6, 7};
83 printf("First Equal : %2d \n", searchFirstEqual(arr, 16, 5));
84 printf("Last Equal : %2d \n", searchLastEqual(arr, 16, 5));
85 printf("First Equal or Larger : %2d \n", searchFirstEqualOrLarger(arr, 16, 5));
86 printf("First Larger : %2d \n", searchFirstLarger(arr, 16, 5));
87 printf("Last Equal or Smaller : %2d \n", searchLastEqualOrSmaller(arr, 16, 5));
88 printf("Last Smaller : %2d \n", searchLastSmaller(arr, 16, 5));
89 return 0;
90 return 0;
91 }
View Code
参考:①你真的会写二分查找吗 - luoxn28 - 博客园
②你真的会写二分检索吗?-liubird- ChinaUnix博客(测试段代码来源)