zoukankan      html  css  js  c++  java
  • Codeforces Edu Round #94 (CF1400)

    掉了点分

    A:

    给定长度为(2n-1)的01字符串(str),求长度为(n)的字符串(ans),使得(ans sim str)

    定义字符串(a sim b)时,有(i)满足(a_i = b_i)


    一道ca大水题,有两种解法:

    1.  /*
       	ID: Loxilante
       	Time: 2020/08/27
       	Prog: CF1400A-1
       	Lang: cpp
       */
       #ifdef ONLINE_JUDGE
       #pragma GCC optimize("O3")
       #endif
       #include <bits/extc++.h>
       #define rep(i, l, r) for(int i = l; i < r; i++)
       #define hrp(i, l, r) for(int i = l; i <= r; i++)
       #define rev(i, r, l) for(int i = r; i >= l; i--)
       #define ms(n, t) memset(n, t, sizeof(n))
       #define pb push_back
       #define int ll
       #ifndef JOEON
       #define D(...) 97
       #endif
       using namespace std;
       typedef long long ll;
       typedef pair<int, int> pii;
       template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
       signed main(void)
       {
       	clock_t Begin = clock();
       
       	#ifdef JOEON
       //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
       //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
       	#endif
       	
       	ios::sync_with_stdio(false);
       	cin.tie(0);
       	
       	int T = next();
       	
       	clock_t InputFinished = clock();
       	
       	while(T--)
       	{
       		int n = next();
       		string str = next<string>();
       		rep(i, 0, n) cout<<str[n-1];
       		cout<<endl;
       	}
       	
       	clock_t End = clock();
       	
       	D((double)(End-Begin)/CLOCKS_PER_SEC);
       	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
       	
       	return 0;
       }
      
    2.  /*
       	ID: Loxilante
       	Time: 2020/08/25
       	Prog: CF1400A
       	Lang: cpp
       */
       #ifdef ONLINE_JUDGE
       #pragma GCC optimize("O3")
       #endif
       #include <bits/extc++.h>
       #define rep(i, l, r) for(int i = l; i < r; i++)
       #define hrp(i, l, r) for(int i = l; i <= r; i++)
       #define rev(i, r, l) for(int i = r; i >= l; i--)
       #define ms(n, t) memset(n, t, sizeof(n))
       #define pb push_back
       #define int ll
       #ifndef JOEON
       #define D(...) 97
       #endif
       using namespace std;
       typedef long long ll;
       typedef pair<int, int> pii;
       template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
       signed main(void)
       {
       	clock_t Begin = clock();
       
       	#ifdef JOEON
       //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
       //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
       	#endif
       	
       	ios::sync_with_stdio(false);
       	cin.tie(0);
       	
       	int T = next();
       	
       	clock_t InputFinished = clock();
       	
       	while(T--)
       	{
       		int l = next();
       		string str = next<string>();
       		for(int i = 0; i < str.length(); i += 2) cout<<str[i];
       
       		cout<<endl;
       	}
       	
       	clock_t End = clock();
       	
       	D((double)(End-Begin)/CLOCKS_PER_SEC);
       	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
       	
       	return 0;
       }
       
      

    读者自证不难。



    B:

    你和随从分别能承重(p, f),现有(cnt_s)把剑和(cnt_w)把斧头,剑重(s),斧重(w),求最多能拿走多少武器。


    考场上花一个小时打(O(1))算法,先(color{red}{PigeonGuGuGu})着。

    下面来考虑(O(cnts))的做法:

    假设(s <= w),也就是剑比斧重。

    枚举自己最多带的剑的数量,算出能带斧的数量。

    让随从带尽可能多的剑,如果带完了再带斧头。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/08/27
    	Prog: CF1400B
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	clock_t Begin = clock();
    
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next<int>();
    	
    	clock_t InputFinished = clock();
    	
    	while(T--)
    	{
    		int y, f, cnts, cntw, s, w, ans = 0;
    		cin>>y>>f>>cnts>>cntw>>s>>w;
    
    		if (s > w) swap(cnts, cntw), swap(s, w);
    
    		hrp(takeSword, 0, cnts) 
    		{
    			if (takeSword*s > y) break;
    
    			int Y = y, F = f, ret = takeSword;
    			Y -= takeSword*s; // i take sword
    
    			int takeSword2 = min(F/s, cnts-takeSword); // follower take sword
    			ret += takeSword2;
    			F -= takeSword2*s;
    
    			ret += min(cntw, Y/w+F/w); // take war axe
    
    			ans = max(ans, ret);
    		}
    		cout<<ans<<endl;
    	}
    	
    	clock_t End = clock();
    	
    	D((double)(End-Begin)/CLOCKS_PER_SEC);
    	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
    	
    	return 0;
    }
    /*
    3
    33 27
    6 10
    5 6
    100 200
    10 10
    5 5
    1 19
    1 3
    19 5
     */
    


    C:

    考场上读假题,罚时杠杠哒


    给定整数(x)和字符串(str)(str_i)等于(1)当且仅当(ans_{i+x})(ans_{i-x})等于(0),求字符串(ans)


    1500的ca,对于这种ca我们可以直接口胡个greedy水过:

    (str_i)等于0时,我们让(ans_{i pm x} = 0)反正没有limit随便瞎搞,不过只有这些这题就配不上1500啦,难点还有(-1)

    不过这也很好操作,遍历(ans),然后判断是否合法,也就是(str_i = 1)时判断(ans_{i pm x})是否等于0,如果等于就输出(-1)1500的ca就是这么好水

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/08/26
    	Prog: CF1400C
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	clock_t Begin = clock();
    
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	
    	clock_t InputFinished = clock();
    	
    	while(T--)
    	{
    		string str = next<string>();
    		int x = next();
    
    		auto in = [=](const int& e)
    		{
    			return 0 <= e && e < str.length();
    		};
    
    		string ans;
    		rep(i, 0, str.length()) ans += '1';
    		rep(i, 0, str.length())
    		{
    			if (str[i] == '0')
    			{
    				int a = i-x, b = i+x;
    				if (in(a)) ans[i-x] = '0';
    				if (in(b)) ans[i+x] = '0';
    			}
    		}
    		bool N = 1;
    		rep(i, 0, str.size())
    		{
    			
    			if (str[i] == '1')
    			{
    				bool no = 1;
    				int a = i-x, b = i+x;
    				if (in(a) && ans[a] == '1') no = 0;
    				if (in(b) && ans[b] == '1') no = 0;
    				if (no) {N = 0; break;}
    			}
    			
    		}
    		if (!N) cout<<-1<<endl;
    		else cout<<ans<<endl;
    	}
    	
    	clock_t End = clock();
    	
    	D((double)(End-Begin)/CLOCKS_PER_SEC);
    	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
    	
    	return 0;
    }
    


    D:

    超级1900大水题,可以用超级ez的dp水过,勉强算个dp吧


    给定数列(w),求满足(w_i == w_k && w_j == w_l (i < j < k < l))的个数。


    考虑到(n <= 3000),可以用(O(n^2))的暴力枚举。

    枚举谁呢? (i, j) ?不妥,(w_k)(w_l)难求。(etc.)。感性推断,理性发现,只有枚举(w_k)(w_j),这样(w_i)(w_l)比较容易知道,也好写。

    思路很简单:开一个(pr)前缀数组和(suf)后缀数组,(pr_{i,j})代表指针i之前等于(j)的个数,(suf_{i,j})代表指针i后等于(j)的个数,这大概也许应该是个dp吧,既然是dp,就得有个像样的转移方程,于是:

    (pr_{i, j} = pr_{i-1, j} + (j == w[i]))

    (suf_{i, j} = suf_{i+1, j} + (j == w[i]))


    Code:

    /*
    	ID: Loxilante
    	Time: 2020/08/26
    	Prog: CF1400D
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    const int U = 3e3+50;
    int pr[U][U], suf[U][U], w[U];
    signed main(void)
    {
    	clock_t Begin = clock();
    
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	
    	clock_t InputFinished = clock();
    	
    	while(T--)
    	{
    		int n = next(), ans = 0;
    		rep(i, 0, n) cin>>w[i];
    
    		ms(pr, 0);
    		ms(suf, 0);
    
    		rep(i, 0, n)
    		{
    			if (i) hrp(j, 0, n) pr[i][j] = pr[i-1][j];
    			pr[i][w[i]]++;
    		}
    
    		rev(i, n-1, 0)
    		{
    			if (i != n-1) hrp(j, 0, n) suf[i][j] = suf[i+1][j];
    			suf[i][w[i]]++;
    		}
    
    		rep(j, 1, n-2) rep(k, j+1, n-1) ans += pr[j-1][w[k]]*suf[k+1][w[j]];
    
    		cout<<ans<<endl;
    	}
    	
    	clock_t End = clock();
    	
    	D((double)(End-Begin)/CLOCKS_PER_SEC);
    	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
    	
    	return 0;
    }
    /*
    Example
    inputCopy
    2
    5
    2 2 2 2 2
    6
    1 3 3 1 2 3
    outputCopy
    5
    2
     */
    

    然后我们发现,这个代码跑了1700ms,用了145000kb,大概是140mb,如果是128mb就要mle了,这时候我们可以压掉一个数组,把 (suf) 数组去掉,用类似前缀和的思想用大减小,这样就只有72000kb,也就是70mb。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/08/26
    	Prog: CF1400D
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    const int U = 3e3+50;
    int pr[U][U], w[U];
    signed main(void)
    {
    	clock_t Begin = clock();
    
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	
    	clock_t InputFinished = clock();
    	
    	while(T--)
    	{
    		int n = next(), ans = 0;
    		rep(i, 0, n) cin>>w[i];
    
    		ms(pr, 0);
    
    		rep(i, 0, n)
    		{
    			if (i) hrp(j, 0, n) pr[i][j] = pr[i-1][j];
    			pr[i][w[i]]++;
    		}
    
    		rep(j, 1, n-2) rep(k, j+1, n-1) ans += pr[j-1][w[k]]*(pr[n-1][w[j]]-pr[k][w[j]]);
    
    		cout<<ans<<endl;
    	}
    	
    	clock_t End = clock();
    	
    	D((double)(End-Begin)/CLOCKS_PER_SEC);
    	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
    	
    	return 0;
    }
    /*
    Example
    inputCopy
    2
    5
    2 2 2 2 2
    6
    1 3 3 1 2 3
    outputCopy
    5
    2
     */
    


    E:

    sharbee重题


    给定一个数列 (w),支持以下操作:

    1. ([l, r])中的元素自减(1).
    2. (w_x)的元素自减(t).

    求最少的操作次数,使数列w变为(0)


    先看题目,仔细一瞧,满足大问题分解成小问题的性质,这时候有两种选择,一是分治,二是dp,我选择分治,因为dp感觉有点难(

    然后考虑分治函数,把一个大序列分解成左,右两个小序列,然后分别求解。

    最后设计函数参数,首先begin, end是必不可少哒,其次我还设置了一个height,表示父问题中最小的元素的值。

    Code:

    /*
    	ID: Loxilante
    	Time: 2019/10/07
    	Prog: CF1400E
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    const int U = 5e3+50;
    int w[U];
    inline int solve(int begin, int end, int height) // [, )
    {
    	if (begin >= end) return 0;
    	int mid = min_element(w+begin, w+end)-w, ans; // 找到最小元素然后分治
    	ans = min(end-begin, solve(begin, mid, w[mid])+solve(mid+1, end, w[mid])+w[mid]-height);
        // end-begin表示把每个元素都清0的个数
    	return ans;
    }
    signed main(void)
    {
    	clock_t Begin = clock();
    
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int n = next();
    	rep(i, 0, n) cin>>w[i];
    	
    	clock_t InputFinished = clock();
    	
    	cout<<solve(0, n, 0)<<endl;
    	
    	clock_t End = clock();
    	
    	D((double)(End-Begin)/CLOCKS_PER_SEC);
    	D((double)(End-InputFinished)/CLOCKS_PER_SEC);
    	
    	return 0;
    }
    

    F和G 一个要用AC自动机,一个要用容斥,懒得写了(

  • 相关阅读:
    P1352 没有上司的舞会
    P1879 [USACO06NOV]玉米田Corn Fields
    P1896 [SCOI2005]互不侵犯
    2019寒假纪中happy之旅
    JZOJ 4249. 【五校联考7day1】游戏
    JZOJ 4248. 【五校联考7day1】n染色
    JZOJ 4252. 【五校联考7day2】QYQ的图
    STM32初学Keil4编译时出现 Error:Failed to execute 'BIN40/Armcc'
    STM32初学Keil4编译时出现 Error:Failed to execute 'BIN40/Armcc'
    重踏学习Java路上_Day02(java 基础上)
  • 原文地址:https://www.cnblogs.com/Loxilante/p/CF1400.html
Copyright © 2011-2022 走看看