5.12省赛前做题

	省赛结束, 省一(实银).
	
	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 ] );//因为是 0  1,表示所以可以,这样处理有无
					}
				}
			}
		}//最后cnt就是总数
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;
				}

			}
		}
	//	for(int i=0;i<v1.size();i++) cout<<v1[i]<<" "; puts("");
	//	for(int i=0;i<v2.size();i++) cout<<v2[i]<<" "; puts("");
	//	for(int i=0;i<v4.size();i++) cout<<v4[i]<<" "; puts("");
		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");
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值