zoukankan      html  css  js  c++  java
  • CSP-J/S2019 做题练习(day1)

    A - Xenny and Alternating Tasks

    题面

    题解

    枚举第一天是谁做,将两个答案取(min)即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    int t, n, a[20003], b[20003];
    
    int main()
    {
    	//File("XENTASK");
    	t = gi();
    	while (t--)
    	{
    		n = gi();
    		for (int i = 1; i <= n; i+=1) a[i] = gi();
    		for (itn i = 1; i <= n; i+=1) b[i] = gi();
    		itn ans = 0, sum = 0;
    		for (itn j = 1; j <= n; j+=1)
    		{
    			if (j & 1) sum = sum + a[j];
    			else sum = sum + b[j];
    		}
    		for (int j = 1; j <= n; j+=1)
    		{
    			if (j & 1) ans = ans + b[j];
    			else ans = ans + a[j];
    		}
    		printf("%d
    ", min(ans, sum));
    	}
    	return 0;
    }
    

    B - Bear and Extra Number

    题面

    题解

    将数列排序,遍历数组元素,然后分类讨论:

    1. 如果是(a_i = a_{i+1}) ,那么输出(a_i)
    2. 如果(a_{i+1}-a_i>1)
      • 因为题目说有唯一解,因此(i)只能为(n-1)(1)
        • (i)(n-1),则输出(a_n)
        • (i)(1),则输出(a_1)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    int t, n, a[100003], ans, sum;
    
    int main()
    {
    	//File("EXTRAN");
    	t = gi();
    	while (t--)
    	{
    		n = gi();
    		for (itn i = 1; i <= n; i+=1) a[i] = gi();
    		sort(a + 1, a + 1 + n);
    		for (int i = 1; i < n; i+=1)
    		{
    			if (a[i + 1] == a[i]) {printf("%d
    ", a[i]); break;}
    			if (a[i + 1] - a[i] > 1)
    			{
    				if (i == n - 1) {printf("%d
    ", a[n]); break;}
    				else if (i == 1) {printf("%d
    ", a[1]); break;}
    			}
    		}
    	}
    	return 0;
    }
    

    C - Cooking Schedule

    题面

    题解

    二分。

    注意(check)怎么写。

    第一次做时没想到二分,很遗憾。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define int long long
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    int n, m, t, k, ans, kkk, c[1000003];
    char s[1000003];
    
    int CCC(itn x)
    {
    	int u = 0;
    	for (int i = 1; i <= n; i+=1)
    	{
    		if (i % 2 == x)
    		{
    			if (s[i] == '0') ++u;
    		}
    		else {if (s[i] == '1') ++u;}
    	}
    	return u;
    }
    
    bool check(int x)
    {
    	if (x != 1)
    	{
    		int u = 0;
    		for (itn i = 1; i <= kkk; i+=1) if (c[i] > x) u = u + c[i] / (x + 1);
    		return u <= k;
    	}
    	else {int u = min(CCC(1), CCC(0)); return u <= k;}
    }
    
    signed main()
    {
    	//File("SCHEDULE");
    	t = gi();
    	while (t--)
    	{
    		int l = 1, r = 0, uuu = 0; kkk = 0;
    		n = gi(), k = gi();
    		scanf("%s", s + 1);
    		for (int i = 1; i <= n; i+=1)
    		{
    			if (s[i] != s[i + 1])
    			{
    				c[++kkk] = i - uuu; uuu = i; r = max(r, c[kkk]);
    			}
    		}
    		while (l < r)
    		{
    			int mid = (l + r) >> 1;
    			if (check(mid)) r = mid;
    			else l = mid + 1;
    		}
    		printf("%lld
    ", r);
    	}
    	return 0;
    }
    
    

    D - Subtree Removal

    题面

    题解

    简单树形(DP)

    看似很难,实际代码很短。

    计算出每棵子树的大小,与(-X)(max)即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <vector>
    #define int long long
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    int t, n, x, fa[100003], ans, sum, k, b[100003], sz[100003];
    vector <int> e[100003];
    
    int dfs(int u, int fa)
    {
    	int o = b[u];
    	for (int i = e[u].size() - 1; ~i; i-=1)
    	{
    		int v = e[u][i];
    		if (v == fa) continue;
    		o = o + dfs(v, u);
    	}
    	return max(o, -x);
    }	   
    
    signed main()
    {
    	//File("SUBREM");
    	t = gi();
    	while (t--)
    	{
    		n = gi(), x = gi();
    		int sum = 0;
    		for (itn i = 1; i <= n; i+=1) b[i] = gi(), sz[i] = b[i], sum = sum + b[i], e[i].clear();
    		for (itn i = 1; i < n; i+=1) {int u = gi(), v = gi(); e[u].push_back(v), e[v].push_back(u);}
    		printf("%lld
    ", dfs(1, -1));
    	}
    	return 0;
    }
    
    

    E - Dish Owner

    题面

    题解

    并查集简单题。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <vector>
    #include <queue>
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    itn t, n, s[10003], fl, x, y, Q;
    itn a[10003], fa[10003];
    
    int getf(itn u) {if (u == fa[u]) return u; return fa[u] = getf(fa[u]);}
    
    inline void unionn(int u, int v) {
    	if (a[u] > a[v])
    	{
    		fa[v] = u;
    	}
    	else if (a[v] > a[u])
    	{
    		fa[u] = v;
    	}
    }
    
    int main()
    {
    	//File("DISHOWN");
    	t = gi();
    	while (t--)
    	{
    		n = gi();
    		for (itn i = 1; i <= n; i+=1) s[i] = gi(), a[i] = s[i], fa[i] = i;
    		Q = gi();
    		for (itn i = 1; i <= Q; i+=1)
    		{
    			fl = gi();
    			if (fl)
    			{
    				x = gi();
    				printf("%d
    ", getf(x));
    			}
    			else
    			{
    				x = gi(), y = gi();
    				int X = getf(x), Y = getf(y);
    				if (X == Y) puts("Invalid query!");
    				else unionn(X, Y);
    			}
    		}
    	}
    	return 0;
    }
    

    F - Triplets

    题面

    题解

    数学题。

    大暴力很好写,考虑如何优化。

    预处理出(a)(c)序列的前缀和。

    逐一枚举(b)序列上的数,找出(a)(c)序列中比当前枚举到的数小的数。

    计算出其对答案的贡献即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define int long long
    #define gI gi
    #define itn int
    #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    const int mod = 1000000007;
    itn t, n, p, q, r, a[100003], b[100003], c[100003], x, y, z;
    itn s1 = 1, s2 = 1, s3 = 1;
    
    signed main()
    {
    	//File("SUMQ");
    	t = gi();
    	while (t--)
    	{
    		p = gi(), q = gi(), r = gi();
    		for (int i = 1; i <= p; i+=1) a[i] = gi();
    		for (int i = 1; i <= q; i+=1) b[i] = gi();
    		for (itn i = 1; i <= r; i+=1) c[i] = gi();
    		sort(a + 1, a + 1 + p); sort(b + 1, b + 1 + q); sort(c + 1, c + 1 + r);
    		int p1 = 1, p2 = 1, c1 = 0, c2 = 0, s1 = 0, s2 = 0, ans = 0;
    	   	for (int i = 1; i <= q; i+=1)
    	   	{
    		   	while (p1 <= p && a[p1] <= b[i])
    		   	{
    		   		s1 = (s1 + a[p1]) % mod;
    		   		++c1, ++p1;
    		   	}
    			while (p2 <= r && c[p2] <= b[i])
    		   	{
    				s2 = (s2 + c[p2]) % mod;
    			   	++c2, ++p2;
    	   		}
    	   		ans = (ans % mod + c1 * c2 % mod * b[i] % mod * b[i] % mod) % mod;
    	   		ans = (ans % mod + b[i] * (s1 * c2 % mod + s2 * c1 % mod) % mod) % mod;
    	   		ans = (ans % mod + s1 * s2 % mod) % mod; 
    	   	}
    	   	printf("%lld
    ", ans % mod);
    	}
    	return 0;
    }
    

    总结

    这次练习第一次做的时候做得一般般。

    做题的策略要更好一点。

    细节地方要注意。

  • 相关阅读:
    List<T>的使用
    onclientclick和onclick区别
    IOS学习资料
    DataTable排序的一般方法
    jquery特效
    交叉表、行列转换和交叉查询经典
    sql截取查询
    DelPhi学习网站
    EasyDarwin开源云平台接入海康威视EasyCamera摄像机之快照获取与上传
    EasyDarwin开源云平台接入海康威视EasyCamera摄像机之快照获取与上传
  • 原文地址:https://www.cnblogs.com/xsl19/p/11277879.html
Copyright © 2011-2022 走看看