zoukankan      html  css  js  c++  java
  • Codeforces Round #627 (Div. 3) 补题

    • CF1324A Yet Another Tetris Problem

      长度为n的数组a中有一组数,可以任意使其中一项+2,问能否使a中所有项的值相同。

      感觉div.3的题目更多地在考简化问题的能力……比如原题目以俄罗斯方块作背景,让我想到的是能不能消除所有方块,导致代码很难写。但如果像上述一样简化题意,方向就很明确了:只要判断是否所有数均为偶数/均为奇数即可。

      $color{green}{CF1324A-代码}$
      #include<cstdio> 
      #include<iostream>
      #include<cstring>
      #include<algorithm>
      #include<set>
      #include<vector>
      #include<queue>
      using namespace std;
      
      int main()
      {
      	int a[110];
      	int kase;
      	cin>>kase;
      	while(kase--){
      		int n;
      		cin>>n;
      		a[0]=a[n+1]=0;
      		int ok=1;
      		for(int i=1;i<=n;i++){
      			cin>>a[i];
      			a[i]%2==0?a[i]=-1:a[i]=-2;//偶数记为-1,奇数记为-2 
      			if(i==1) continue;
      			if(a[i]!=a[1]) ok=0;
      		}
      		if(ok) cout<<"YES"<<endl;
      		else cout<<"NO"<<endl;
      	}
      	return 0;
      }
      
      

    • CF1324B Yet Another Palindrome Problem

      判断a串中是否存在长度3及以上的回文子串
      简化问题:是否存在长度3的回文子串
      再简化:是否存在两个不相邻的相等元素

      简化到核心部分已经直接表明代码应该怎么写了……但是具体细节还是要展开一下:

      在遍历a串的过程中,用vis数组标记遇到的数字,并记录这个数字第一次出现时的下标。如果遍历到的数字是第二次遇到((vis[a[i]]!=0)), 那么与第一次遇到该数字的位置作个距离计算,只要(>1)就能说明不相邻,可以作为首尾构成回文子串。

      $color{green}{CF1324B-代码}$

      #include<cstdio> 
      #include<iostream>
      #include<cstring>
      #include<algorithm>
      #include<set>
      #include<vector>
      #include<queue>
      using namespace std;
      
      int a[5010];
      int vis[5010]; 
      int main()
      {
      	int t;
      	cin>>t;
      	while(t--){
      		memset(a,0,sizeof(a));
      		memset(vis,0,sizeof(vis));
      		int n;
      		cin>>n;
      		int ok=0;
      		for(int i=1;i<=n;i++) {
      			cin>>a[i];
      			if(!vis[a[i]]) vis[a[i]]=i;
      			else if(i-vis[a[i]]>1) ok=1;
      		}
      		if(ok) cout<<"YES"<<endl;
      		else cout<<"NO"<<endl;
      	}
      	return 0;
      }
      
      

    • CF1324C Frog Jumps

      一只青蛙跳方格,只能向左向右跳。起点只能向右跳。其它格子写有L、R,代表青蛙在此方格上后的跳跃方向。青蛙可以选择一个距离(d),每一次跳跃都可以跳到距离(<=d)的格子上,问可以跳到终点的最小的(d)

      逆向思考一波。显然终点只能由离它最近的R格子跳过去,但我当时的思考就到这里了,然后就卡住了……

      结合题意,对于两个间接相邻的R格子,总是可以从右边的R格子跳到左边的R格子(因为它们之间必定是连续的L),如果逆向思考,我们也只能这样跳回起点——也就是说,只要考虑路上所有间接或直接相邻的R格子的之间的距离,取其中最大值,就能保证选用的(d)可以从终点跳回起点。

      $color{green}{CF1324C-代码}$

      #include<cstdio> 
      #include<iostream>
      #include<cstring>
      #include<algorithm>
      #include<set>
      #include<vector>
      #include<queue>
      using namespace std;
      
      int main()
      {
      	int t;
      	cin>>t; 
      	while(t--){
      		string a="R";
      		string x;
      		cin>>x;
      		a+=x;
      		int last=0;
      		int m=0;
      		for(int i=0;i<a.length();i++){
      			if(a[i]=='R'){
      				m=max(m,i-last);
      				last=i;
      			}
      		}
      		int ans;
      		int k=a.length()-last;
      		ans=max(m,k);
      		cout<<ans<<endl;
      	}
      	return 0;
      }
      
      

    CF1324D Pair of Topics

    给定两个长度为 (n) 的序列,求满足 (a_i+a_j>b_i+b_j) ((i<j))((i,j))对数

    (2·10^5)的数据量显然不是用来暴力的……

    将式子变形为

    [a_i-b_i>b_j-a_j ]

    也就是

    [a_i-b_i>-(a_j-b_j) ]

    (c_i=a_i-b_i),上式即

    [c_i+c_j>0 quad (i<j) ]

    找出满足该条件的((i,j))对数即可。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 200000 + 10;
    typedef long long LL;
    LL a[maxn], b[maxn],c[maxn];
    int main() {
    	int n;
    	cin >> n;
    	for (int i = 1;i <= n;i++) cin >> a[i];
    	for (int i = 1;i <= n;i++) cin >> b[i];
    	for (int i = 1;i <= n;i++) c[i] = a[i] - b[i];
    	LL ans = 0;
    	sort(c + 1, c + 1 + n);
    	for (int i = 2;i <= n;i++) {
    		int k = upper_bound(c + 1, c + i, -c[i]) - c;
    		//在给定区间内找到第一个大于-c[i]的数的迭代器,-c得下标
    		//因为是以c[i]为右端点,所以只会统计一次而不用担心不会满足i<j,并且无论c[i]是正是负均可
    		ans += i - k;//从下标k开始到区间右端点i 都是满足条件的数
    	}
    	cout << ans;
    	return 0;
    }
    

    CF1324E Sleeping Schedule

    又到了喜闻乐见的简化问题时间:给定一个数组(a),可以让其中一些减(1)(也可以不减),问前缀和数组对(h)取模后在区间([L,R])内的元素最多有多少个。

    简化成前缀和数组这个没有想到,相关问题几乎没有做过。不过倒是看出来了是个(DP)题,但是没想好(DP)数组应该表示什么……

    考虑令(dp[i][j])表示当(displaystyle sum_{k=1}^i{a_k}) (\%h=j)时,答案最大为多少。

    则转移方程思路:对于第(i)个数(a_i),减1或不减1,在两种方案中取答案数大的,并且只有在([L,R])内的才计数

    (dp[i][j]=max(dp[i-1][(j-a[i]+h)\%h],dp[i-1][j-a[i]+1+h)\%h])+(L<=j&&j<=R))

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<chrono>
    
    using namespace std;
    
    const int N = 2e3 + 10;
    int n, h, L, R, a[N], dp[N][N];
    
    int Inc(int x) {
    	return (x + h) % h;
    }
    
    int check(int x) {
    	return L <= x && x <= R;
    }
    
    int main()
    {
    	memset(dp, -63, sizeof(dp));//赋一个极小值,不能是-1
    	dp[0][0] = 0;
    	cin >> n >> h >> L >> R;
    	for (int i = 1;i <= n;i++) cin >> a[i];
    
    	for (int i = 1;i <= n;i++) {
    		for (int j = 0;j < h;j++) {
    			dp[i][j] = max(dp[i - 1][Inc(j - a[i])], dp[i - 1][Inc(j - a[i] + 1)]) + check(j);
    		}
    	}
    
    	int Max = 0;
    	for (int i = 0;i < h;i++) Max = max(Max, dp[n][i]);//在所有睡够n次的结果中找最大值
    	cout << Max;
    	return 0;
    }
    

  • 相关阅读:
    开源软件的国内镜像
    ruby学习之路(一)
    VBS正则表达式
    fscanf和feof的组合使用
    计算机产生随机数
    常用:JQ
    unitegallery 测试使用-自动播放关闭
    H5重力感应(转)
    JS中,如何判断一个数是不是小数?如果是小数,如何判断它是几位小数 保留n位小数
    input禁止显示历史输入记录
  • 原文地址:https://www.cnblogs.com/streamazure/p/12590358.html
Copyright © 2011-2022 走看看