省赛结束, 省一(实银).
1.按日期来记
2.记录题目难度,解法简单表述
3.~~随时断更~~
4.17
~~**2018JSCPC签到题** K题~~ ~~待补,鸽了~~
~~**[a,b] [c,d] 区间内任取x, y , y - x 为 **2018** 的倍数**~~
1. 求最小D,是的a[i] 加或者减 一次,整个数列都相等,不存在,输出-1;
题目链接 : http://codeforces.com/contest/1154/problem/B
做法:
1.set判断不同数的个数,大于3,必然不存在.
2.等于3 判断前后差
3.等于2.判断是否取中值 (2 , 8 输出3 ,1 6 输出 5)
4.等于1,输出0
4.18
终于忙完了,傻逼的事.当你觉得那是理所当然的事时,那就已经很不合常理了.做题.
1.现有一个,装有n个球的的盒子.
First : 依次加入一个盒子.从每个已有的盒子里取出一个球放入新加入的盒子.
Second : 把球个数为0的盒子拿走,重复上述操作
有这样一种情况,一开始装有3个球,加入一个盒子后,有两个盒子分别装有1 、2两个球.执行如上操作,任然是1、2.
先给定 初始球的总数 n ,问你,实现这种操作最多能用多少个球来实现这种循环
题目链接:http://acm.hhu.edu.cn/problem.php?id=1109
做法 :
显然(划掉),当k*(k+1)<=n时,取到最大值.即只有当出现盒子装球个数为 1、2、3... k - 1、 k 才可能循环.
2.给定数组,不能选择相邻的,求选出的最大和
简单dp
题目链接: https://ac.nowcoder.com/acm/contest/558/I
做法 : dp[n][0]表示选择当前数 ,dp[n][1]表示不选当前数
转移方程
dp[i][0]=dp[i-1][0]+a[i]; 选当前,前一个不选(dp[i-1][0])+当前值
dp[i][1]=max{ dp[i-1][0],dp[i-1][1] };不选这个数,从前一次找到最大值
还有一种解法
int dp[ n] [ n+ 1 ] , a[ n] ; int ans ( 0 ) ;
dp[ 0 ] [ 1 ] = a[ 0 ] ;
for ( int i= 1 ; i< n; i++ ) {
for ( int j= 0 ; j< i+ 1 ; j++ ) {
dp[ i] [ j] = dp[ i- 1 ] [ j] ;
if ( abs ( i+ 1 - j) != 1 ) dp[ i] [ i+ 1 ] = max ( dp[ i- 1 ] [ j] + a[ i] , dp[ i] [ i+ 1 ] ) ;
}
}
for ( int i= 0 ; i<= n; i++ ) ans = max ( ans, dp[ n- 1 ] [ i] ) ;
自行理解一下.
4.19 ( 每次也就只能写写人类智慧题了
1.给出三视图,让你求方块个数
题目链接 : http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1008&cid=846
做法 : 1.记录三个视角的图形数组
2.模拟数方块,从主视角来看,对主视角为 1 的方块,依据侧视图,和俯视图 易得( b[ i ][ k ] * c[ k ] [ j ]),即可得出此坐标是否有方块.
3.(看着魔方写的
代码: b , c 是 侧视图 , 和 俯视图 ; 重点在于选取一个视角为主
for ( int i= 1 ; i<= x; i++ ) {
for ( int j= 1 ; j<= y; j++ ) {
if ( a[ i] [ j] == 1 ) {
for ( int k= 1 ; k<= z; k++ ) { / / 另外两个视角结合
cnt+ = ( b[ j ] [ k ] * c[ k ] [ i ] ) ;
}
}
}
}
2.一场比赛写了一题(划掉
4.20( 详见开头第三点 )
4.21
1.求并查集最大集团
题目链接 : http://acm.hhu.edu.cn/problem.php?id=1818
做法:num数组记录集团人数,在merge函数里就能求出最大值.
代码 :
void merge ( int x, int y) {
int fx= find ( x) ; int fy= find ( y) ;
if ( fx!= fy) {
pre[ fy] = fx;
num[ fx] + = num[ fy] ;
if ( num[ fx] > maxn) maxn= num[ fx] ;
}
}
注意点: n == 0 , 特判输出 1,WA * 1 ; 数组开小 , WA * 2;
2.从给定起点,连边,使得途中最长路径最短~~待做~~
3.欧几里得游戏:给定两个自然数,辗转相除,不能操作的最后一个为输
题目链接: http://acm.hhu.edu.cn/problem.php?id=1402
做法 :a始终较大
1.a % b==0 时,必胜
2.a<2*b,没得操作 a=a-b
3.a>2*b,此时分析一下,~~(由于都是最优操作所以必胜)~~
4.22-4.25挂机+挂科
4.26 codeforces div3 上分场( 三题+偷了一题的思路
题意:从数组两端取出一个严格增序列,输出最长取法
题目链接:http://codeforces.com/contest/1157/problem/C2
做法: 1.记录大的,取比上次取值的,大的较小值
2.遇到相同的,就遍历两个序列,因为严格增,取了一端后,就一定不选另一端(这是偷的思路
代码:
while ( top!= ed) {
if ( a[ top] > temp&& a[ ed] > temp) {
if ( a[ top] < a[ ed] ) { temp = a[ top] ; v. push_back ( 'L' ) ; top++ ; }
else if ( a[ ed] < a[ top] ) { temp= a[ ed] ; v. push_back ( 'R' ) ; ed-- ; }
else {
flag= 1 ;
for ( int i= top; i< ed; i++ ) {
if ( a[ i+ 1 ] > a[ i] ) cnt1++ ;
else break ;
}
for ( int i= ed; i> top; i-- ) {
if ( a[ i- 1 ] > a[ i] ) cnt2++ ;
else break ;
}
break ;
}
} else if ( a[ top] > temp) {
temp= a[ top] ; v. push_back ( 'L' ) ; top++ ;
} else if ( a[ ed] > temp) {
temp= a[ ed] ; v. push_back ( 'R' ) ; ed-- ;
} else break ;
}
if ( top== ed&& a[ top] > temp) v. push_back ( 'L' ) ;
if ( flag) ans= max ( cnt1, cnt2) ;
else ans= 0 ;
cout<< ans+ v. size ( ) << endl;
4.27[ ZOJ ] 2019.浙江省赛 E
题意 : 把一个数放到第一位,称为一次操作,求最少操作次数使得数组 非减
题目链接: http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5993
做法:从最后一位遍历入栈
1.若下一个数大于栈顶,就把栈顶删到不小于这个数,加入栈把删去的最大数,记录下来用来比较.
2.下一个数只有大于被删去最大数,且小于等于栈顶才加入
3.没想到怎么记录删去最大值,就用vector,T警告
代码: stack<int >st;
for ( int i= n; i>= 1 ; i-- ) {
if ( a[ i] <= maxn&& a[ i] >= minn) {
cnt++ ;
maxn= a[ i] ;
st. push ( a[ i] ) ;
} else if ( a[ i] > maxn) {
int tp= a[ i] ;
vector< int > v;
while ( ( cnt>= 1 ) && tp > st. top ( ) ) {
v. push_back ( st. top ( ) ) ;
st. pop ( ) ; cnt-- ;
}
maxn= a[ i] ;
if ( v. size ( ) >= 1 ) minn= max ( v[ v. size ( ) - 1 ] , minn) ;
st. push ( a[ i] ) ; cnt++ ;
}
}
~~个人总结:真就挂机三小时啊 , 我带你们打~~
4.29
1.题意:求一个数组(有序),前后差不超过5的最大数组长度
题目链接:http://codeforces.com/contest/1133/problem/C
做法:
类似http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5993
要点:
1.入队,去掉队列不符合的前部
2.队列要判空,否则会SE
3.q.size()返回值不是int么.为什么加强制转换才行(待解
代码:
for ( int i= 1 ; i<= n; i++ ) {
if ( q. empty ( ) || a[ i] - q. front ( ) <= 5 ) {
q. push ( a[ i] ) ;
} else if ( ( a[ i] - q. front ( ) ) > 5 ) {
v. push_back ( ( int ) ( q. size ( ) ) ) ;
while ( ( ! q. empty ( ) ) && ( a[ i] - q. front ( ) ) > 5 ) {
q. pop ( ) ;
}
q. push ( a[ i] ) ;
}
}
2.题意求生成树,是某点度最大
题目链接:http://codeforces.com/contest/1133/problem/F1
做法:找到最大,,建图然后bfs
要点:
1.用了一个变量maxn记录了两个值(最大值,最大值位置),然后过了两个样例??
2.改了过了,
3.有生成树做法(没看(懂),不会
4.貌似题目没说一定有解. (当然也没说没解怎么处理
5.是否有前驱来记录是否已访问过,少了一个vis数组
代码:
queue< int > q;
q. push ( x) ;
int now, ed;
while ( ! q. empty ( ) ) {
now= q. front ( ) ;
q. pop ( ) ;
int l= ( int ) ( v[ now] . size ( ) ) ;
for ( int i= 0 ; i< l; i++ ) {
int t= v[ now] [ i] ;
if ( pre[ t ] == t && t!= x) {
q. push ( t ) ;
pre[ t] = now;
}
}
}
for ( int i= 1 ; i<= n; i++ ) {
if ( pre[ i] == i) continue ;
cout<< pre[ i] << " " << i<< '\n' ;
}
3.题意:最优d,使得d * a[ i ]+b[ i ] = 0 ,成立的式子的最大个数
题目链接:http://codeforces.com/contest/1133/problem/D
做法 :
1.结构体表示分数 , 化简
2. 负数kd=-1,正数kd=1
up=0,down=0,直接计数tot1
up=0,down!=0,直接忽略
down=0,up!=0,kd=0,统一设为 up= 0 , down = 1
3.输出 tot1 + maxn
4.cmp函数爆int,WA on 23 ,WA*6
代码:
struct P{
ll up, down;
int kd;
}
bool cmp ( P x , P y) {
if ( x. kd== y. kd) return ( x. up* y. down) < ( x. down* y. up) ;
return x. kd< y. kd;
}
P tmp= p[ 1 ] ; tot= 0 ;
for ( int i= 1 ; i< cnt; i++ ) {
if ( p[ i] . up== tmp. up&& p[ i] . down== tmp. down&& p[ i] . kd== tmp. kd) {
tot++ ;
} else {
maxn= max ( tot, maxn) ;
tot= 1 ;
tmp= p[ i] ;
}
}
4.30
题意 : 构造回文矩阵
题目链接:http://codeforces.com/contest/1118/problem/C
做法: 大模拟
代码 :
if ( n% 2 == 0 ) {
while ( ! q. empty ( ) ) {
now= q. front ( ) ; q. pop ( ) ;
while ( mp[ now] != 0 && mp[ now] % 4 == 0 ) {
mp[ now] - = 4 ;
v4. push_back ( now) ;
}
if ( mp[ now] != 0 ) break ;
}
int mid= n/ 2 ;
if ( v4. size ( ) == ( n* n/ 4 ) ) {
puts ( "YES" ) ;
for ( int i= 1 ; i<= n; i++ ) {
for ( int j= 1 ; j<= n; j++ ) {
int k= 0 ;
if ( i<= mid) k+ = ( i- 1 ) * mid;
else k+ = ( n- i) * mid;
if ( j<= mid) k+ = j;
else k+ = ( n- j+ 1 ) ;
printf ( "%d" , v4[ k- 1 ] ) ;
j== n? puts ( "" ) : printf ( " " ) ;
}
}
} else puts ( "NO" ) ;
} else {
while ( ! q. empty ( ) ) {
now= q. front ( ) ; q. pop ( ) ;
while ( mp[ now] != 0 ) {
if ( mp[ now] % 4 == 0 && v4. size ( ) < ( n- 1 ) * ( n- 1 ) / 4 ) {
v4. push_back ( now) ;
mp[ now] - = 4 ;
continue ;
}
if ( mp[ now] % 2 == 0 ) {
v2. push_back ( now) ;
mp[ now] - = 2 ;
continue ;
}
if ( mp[ now] % 2 == 1 ) {
v1. push_back ( now) ;
mp[ now] - = 1 ;
continue ;
}
}
}
if ( v4. size ( ) != ( ( n- 1 ) * ( n- 1 ) / 4 ) || v2. size ( ) != ( n- 1 ) || v1. size ( ) != 1 ) puts ( "NO" ) ;
else {
puts ( "YES" ) ;
int mid= ( n+ 1 ) / 2 ; int md= ( n- 1 ) / 2 ;
for ( int i= 1 ; i<= n; i++ ) {
for ( int j= 1 ; j<= n; j++ ) {
int k = 0 ;
if ( i== mid) {
if ( j== mid) {
printf ( "%d" , v1[ 0 ] ) ;
}
else if ( j< mid) {
k= md+ j;
printf ( "%d" , v2[ k- 1 ] ) ;
} else {
k= md+ ( n- j+ 1 ) ;
printf ( "%d" , v2[ k- 1 ] ) ;
}
} else if ( i< mid) {
if ( j== mid) {
k= i;
printf ( "%d" , v2[ k- 1 ] ) ;
}
else if ( j< mid) {
k= md* ( i- 1 ) + j;
printf ( "%d" , v4[ k- 1 ] ) ;
} else {
k= md* ( i- 1 ) + ( n- j+ 1 ) ;
printf ( "%d" , v4[ k- 1 ] ) ;
}
} else {
if ( j== mid) {
k= ( n- i+ 1 ) ;
printf ( "%d" , v2[ k- 1 ] ) ;
}
else if ( j< mid) {
k= md* ( n- i) + j;
printf ( "%d" , v4[ k- 1 ] ) ;
} else {
k= md* ( n- i) + ( n- j+ 1 ) ;
printf ( "%d" , v4[ k- 1 ] ) ;
}
}
j== n? puts ( "" ) : printf ( " " ) ;
}
}
}
}
5.1 2018JSCPC
B 题意: 太复杂鸽了(划掉
The h-index of an author is the largest h where he has at least h papers with citations not less than h.
(自行理解这句话
论文有一个属性为引用数,工作x小时,可以使论文的引用数为( a * x ), a为给定的值 , 求给定工作时间,求作者的 h ;
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6277
做法 : 冷静分析,盲猜(a+n)/2; 然后AC了(真实
代码 : 输出两个数 a , n 的平均数
F 题意: 给定有序数对(3个数),求满足不等式的 有序数对 全排列(使给出有序数对的顺序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6281
做法:
1.简单结构体排序,相等取 id 小的;
2.不化简会爆 ll? 化简了过了;
代码:
struct P{
int id;
ll a, b, c; ll sm1;
} p[ 4003 ] ;
bool cmp ( P s1, P s2) {
if ( ( s1. sm1* s2. c) == ( s1. c* s2. sm1) ) return s1. id< s2. id;
return ( ( s1. sm1* s2. c) ) < ( ( s1. c* s2. sm1) ) ;
}
G 题意:给定字符串 S 仅含abc,可以删去 {aa, bb ,abab },给定 T ,能否从 S 变为 T ;
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6282
做法:
1. 根据样例,猜到,能实现的功能仅为,删去 aa,bb ,abab, 调换 ab位置 (从ab 到ba );
2.那么,对于一个给定S,以 c 为分界线,每段上,一定可以化简为空串(a,b个数为偶数时),含a,b仅一个(当 a 个数为奇, b 个数为奇数 );
代码: 丑、写烦了(虽然思路清晰(假)
bool flag= 0 ;
pair< int , int > p1[ 10005 ] , p2[ 10005 ] ;
int l1= strlen ( a) ; cnt1= 1 ;
for ( int i= 0 ; i< l1; i++ ) {
int t= a[ i] - 'a' ;
if ( t== 2 ) {
cnt1++ ;
} if ( t== 0 ) {
p1[ cnt1] . first++ ;
} if ( t== 1 ) {
p1[ cnt1] . second++ ;
}
}
int l2= strlen ( b) ; cnt2= 1 ;
for ( int i= 0 ; i< l2; i++ ) {
int t= b[ i] - 'a' ;
if ( t== 2 ) {
cnt2++ ;
}
if ( t== 0 ) {
p2[ cnt2] . first++ ;
}
if ( t== 1 ) {
p2[ cnt2] . second++ ;
}
}
if ( cnt1!= cnt2) {
puts ( "No" ) ; continue ;
}
for ( int i= 1 ; i<= cnt1; i++ ) {
p1[ i] . first% = 2 ;
p1[ i] . second% = 2 ;
}
for ( int i= 1 ; i<= cnt2; i++ ) {
p2[ i] . first% = 2 ;
p2[ i] . second% = 2 ;
}
for ( int i= 1 ; i<= cnt1; i++ ) {
if ( ( p1[ i] . first!= p2[ i] . first) || ( p1[ i] . second!= p2[ i] . second) ) {
flag= 1 ;
break ;
}
}
if ( flag) puts ( "No" ) ;
else puts ( "Yes" ) ;
}