zoukankan      html  css  js  c++  java
  • gym100712 ACM Amman Collegiate Programming Contest

    非常水的手速赛,大部分题都是没有算法的。巨慢手速,老年思维。2个小时的时候看了下榜,和正常人差了3题(,最后还没写完跑去吃饭了..

    A 水 Sort 比大小

    /** @Date    : 2017-09-01 12:32:08
      * @FileName: A.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    struct yuu
    {
    	string na;
    	int s, p;
    }a[110];
    
    int cmp(yuu a, yuu b)
    {
    	if(a.s == b.s)
    		return a.p < b.p;
    	return a.s > b.s;
    }
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		int n;
    		cin >> n;
    		int s, p;
    		string na;
    		for(int i = 0; i < n; i++)
    		{
    			cin >> a[i].na >> a[i].s >> a[i].p;  
    		}
    		sort(a, a + n, cmp);
    		cout << a[0].na << endl;
    	}
        return 0;
    } 

    B 水 枚举位置 猜拳,已经给定了出拳顺序,枚举石布临界,布剪临界的两个位置就好

    /** @Date    : 2017-09-01 13:37:22
      * @FileName: B.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    
    int r[1100], s[1100], p[1100];
    int n;
    char a[1100];
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		int n;
    		MMF(r);
    		MMF(s);
    		MMF(p);
    		scanf("%d", &n);
    		scanf("%s", a + 1);
    		for(int i = 1; i <= n; i++)
    		{
    			if(a[i] == 'R')
    				r[i]++;
    			else if(a[i] == 'S')
    				s[i]++;
    			else p[i]++;
    			r[i] += r[i - 1];
    			s[i] += s[i - 1];
    			p[i] += p[i - 1];
    		}
    		int ans = 0;
    		for(int i = 0; i <= n; i++)
    		{
    			for(int  j = 0; j + i <= n; j++)
    			{
    				int w = s[i] - s[0] + r[i + j] - r[i] + p[n] - p[i + j];
    				int l = p[i] - p[0] + s[i + j] - s[i] + r[n] - r[i + j];
    				if(w > l)
    					ans++;
    			}	
    		}
    		printf("%d
    ", ans);
    	}
        return 0;
    } 

    C 水 标记 一个*覆盖掉3个格子,先处理好,再扫一遍

    /** @Date    : 2017-09-01 12:48:52
      * @FileName: C.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    
    char a[110];
    int vis[110];
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		int n;
    		MMF(a);
    		MMF(vis);
    		cin >> n >> a;
    		for(int i = 0; i < n; i++)
    		{
    			if(a[i] == '*')
    				vis[i] = vis[i - 1] = vis[i + 1] = 1;
    		}
    		int cnt = 0;
    		for(int i = 0; i < n; i++)
    		{
    			if(a[i] == '.' && vis[i] == 0)
    				cnt++, vis[i] = vis[i + 1] = vis[i + 2] = 1;
    			//cout << a[i];
    		}
    		cout << cnt << endl;
    	}
        return 0;
    } 

    D DP 求把一个01串分成均不大于k长度且不是交替串的最小次数。对于任意位置起始的串,在延伸k长度内如果不是交替串那么可以进行转移,预处理出所有区间是否是交替串,DP转移,然后最后的k长度内里选个合法的最小值就行

    /** @Date    : 2017-09-01 15:59:40
      * @FileName: D.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int vis[1010][1010];
    int dp[1010];
    char a[1010];
    int n, k;
    
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%d%d", &n, &k);
    		scanf("%s", a + 1);
    		MMF(vis);
    		for(int i = 1; i <= n; i++)
    		{
    			for(int j = i + 1; j <= n; j++)
    			{
    				if(a[j] == a[j - 1] || vis[i][j - 1])
    					vis[i][j] = 1;
    				else vis[i][j] = 0;
    			}
    			vis[i][i] = 1;
    		}
    
    
    		MMI(dp);
    		dp[1] = 0;
    		for(int i = 1; i < n; i++)
    		{
    			for(int j = 1; j <= k; j++)
    			{
    				if(j + i <= n && vis[i][i + j - 1])
    					dp[i + j] = min(dp[i] + 1, dp[i + j]);
    			}
    		}
    		int mi = INF;
    		for(int i = n - k + 1; i <= n; i++)
    		{
    			if(vis[i][n])
    				mi = min(mi, dp[i]);
    		}
    		printf("%d
    ", mi);
    	}
        return 0;
    } 

    E 水 所有值均加上一定值使其中的最大值不超过100,问最终超过50的有多少个 之前题意还看错...英语太差

    /** @Date    : 2017-09-01 12:39:07
      * @FileName: E.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int a[110];
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		int n;
    		scanf("%d", &n);
    
    		int ma = 0;
    		for(int i = 0; i < n; i++)
    		{
    			scanf("%d", a + i);
    			ma = max(ma, a[i]);
    		}
    		int cnt = 0;
    		for(int i = 0; i < n; i++)
    		{
    			if(a[i] + 100 - ma >= 50)
    				cnt++;
    		}
    		printf("%d
    ", cnt);
    	}
        return 0;
    } 

    F kruskal 给图问走遍所有点的一条路径中,求其中最大的边权值的最小值。 完全就是kruskal的过程。

    /** @Date    : 2017-09-01 15:08:39
      * @FileName: F.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    /*typedef struct sion
    {
    	int nxp;
    	int dis;
    	sion(){};
    	sion(int n, int d):nxp(n),dis(d){}
    }yuu;
    vector<sion>edg[N];
    int dic[N];
    int vis[N];
    int n, m;
    
    int prim(int n)
    {
    	MMI(dic);
    	MMF(vis);
    	for(auto i : edg[1])
    		dic[i.nxp] = i.dis;
    	dic[1] = 0;
    	vis[1] = 1;
    	for(int i = 1; i <= n - 1; i++)
    	{
    		int tmp = INF, np;
    		for(int j = 1; j <= n; j++)
    		{
    			if(!vis[j] && tmp > dic[j])
    				tmp = dic[j], np = j;
    		}
    		if(tmp == INF)
    			return 0;
    		vis[np] = 1;
    		for(auto j: edg[np])
    		{
    			if(!vis[j.nxp] && (j.dis) < dic[j.nxp])
    				dic[j.nxp] = (j.dis);
    		}
    	}
    	int ma = 0;
    	for(int i = 2; i <= n; i++)
    		ma = max(dic[i], ma);
    	return ma;
    }*/
    
    struct edge
    {
    	int u, v, w;
    }edg[N];
    int n, m;
    int fa[N];
    
    int find(int x)
    {
    	if(x != fa[x])
    		fa[x] = find(fa[x]);
    	return fa[x];
    }
    
    int cmp(edge a, edge b)
    {
    	return a.w < b.w;
    }
    
    int join(int a, int b)
    {
    	int x = find(a);
    	int y = find(b);
    	if(x != y)
    	{
    		fa[y] = x;
    		return 1;
    	}
    	return 0;
    }
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%d%d", &n, &m);
    		for(int i = 0; i <= n; i++)
    			fa[i] = i;
    		for(int i = 0; i < m; i++)
    		{
    			int u, v, w;
    			scanf("%d%d%d", &edg[i].u, &edg[i].v, &edg[i].w);
    		}
    		sort(edg, edg + m, cmp);
    
    		int cnt = 0;
    		int ma = 0; 
    		for(int i = 0; i < m && cnt < n; i++)
    		{
    			if(join(edg[i].u, edg[i].v))
    			{
    				cnt++;
    				ma = edg[i].w;
    			}
    		}
    		printf("%d
    ", ma);
    	}
        return 0;
    } 

    G 状态枚举 最多10个物品要求取物品值的和不小于s,拿掉其中最小的后的值要小于s。 开始还在DP想啊想,就10个数用什么DP阿...

    /** @Date    : 2017-09-01 14:31:31
      * @FileName: G.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    
    int n, k;
    int a[1210];
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%d%d", &n, &k);
    		for(int i = 0; i < n; i++)
    			scanf("%d", a + i);
    		int ma = 0;
    		for(int i = 0; i < (1 << n); i++)
    		{
    			int s = 0;
    			int mi = INF;
    			int cnt = 0;
    			for(int j = 0; j < n; j++)
    			{
    				if(((1 << j) & i))
    					s += a[j], cnt++, mi = min(mi, a[j]);
    			}
    			if(s >= k && s - mi < k)
    				ma = max(cnt, ma);
    		}
    		printf("%d
    ", ma);
    	}
        return 0;
    } 

    H(补) tarjan缩点 树的直径 题目问给图上加一条边,使图上的桥的数量最小,问数量。第一次碰到比较简单可以用tarjan,趁这个机会学一下...题目的思路是先求出所有桥,然后剩下的连通块分别缩点,重新建成树。此时树上的边都是桥,最后加边的话只要找树上两点距离最大的,也就是树的直径。这样就能保证包含最多的桥。

    /** @Date    : 2017-09-04 21:09:38
      * @FileName: H tarjan缩点 树的直径.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    struct sion
    {
    	int to, nxt;
    	bool flag; //is bridge
    };
    sion edg[N*2];
    int low[N], dfn[N];
    int fa[N];
    stack<int>stk;
    bool instk[N];
    int bridges;//桥
    int block;//边双连通块
    int idx;
    ////
    int head[N], tot/*, nxt[N], isbg[N], to[N]*/;
    
    void add(int x, int y)//前向星
    {
    	edg[tot].to = y;
    	edg[tot].nxt = head[x];
    	edg[tot].flag = 0;
    	head[x] = tot++;
    }
    void init()
    {
    	MMF(dfn);
    	MMF(instk);
    	MMG(head);
    	idx = block = bridges = tot = 0;
    	while(!stk.empty())
    		stk.pop();
    }
    void tarjan(int x, int pre)
    {
    	low[x] = dfn[x] = ++idx;
    	stk.push(x);
    	instk[x] = 1;
    	for(int i = head[x]; ~i; i = edg[i].nxt)
    	{
    		int np = edg[i].to;
    		if(np == pre)
    			continue;
    		if(!dfn[np])
    		{
    			tarjan(np, x);
    			low[x] = min(low[np], low[x]);
    			if(low[np] > dfn[x])
    			{
    				bridges++;
    				edg[i].flag = 1;
    				edg[i ^ 1].flag = 1;//注意双向
    			}
    		}
    		else if(instk[np])
    			low[x] = min(dfn[np], low[x]);
    	} 
    	if(low[x] == dfn[x])
    	{
    		int np;
    		block++;
    		do{
    			np = stk.top();
    			stk.pop();
    			instk[np] = 0;
    			fa[np] = block;
    		}while(np != x);
    	}
    }
    ////
    int k = 0, pos = -1;
    int n, m;
    int dfs(int x, int pre, int dep)
    {
    	if(k < dep)
    		k = dep, pos = x;
    	for(int i = head[x]; ~i; i = edg[i].nxt)
    	{
    		int np = edg[i].to;
    		if(np == pre)
    			continue;
    		dfs(np, x, dep + 1);
    	}
    }
    ////
    int xx[N], yy[N];
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		init();
    		scanf("%d%d", &n, &m);
    		for(int i = 1; i <= m; i++)
    		{
    			scanf("%d%d", xx + i, yy + i);
    			add(xx[i], yy[i]);
    			add(yy[i], xx[i]);
    		}
    
    		tarjan(1, 0);
    		tot = 0;
    		MMG(head);
    		LL ans = 0;
    		for(int i = 1; i <= m; i++)
    		{
    			int x = fa[xx[i]];
    			int y = fa[yy[i]];
    			if(x != y)
    			{
    				ans++;
    				add(x, y);
    				add(y, x);
    			}
    		}
    		k = 0;
    		dfs(1, -1, 0);
    		k = 0;
    		dfs(pos, -1, 0);
    		printf("%lld
    ", (ans - k)<0?0:ans-k);
    	}
        return 0;
    } 

    I 暴力枚举 使用固定长度的区间,可以把区间的数字同时加,问最大使用多长的区间,能把所有数字变成一样 暴力枚举每一种长度, 主要就是check该长度下是否合法的写法问题

    /** @Date    : 2017-09-14 19:52:52
      * @FileName: I 枚举 暴力.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    
    char s[500];
    
    int check(int k)
    {
    	int len = strlen(s + 1);
    	int q[500];
    	for(int i = 0; i < 10; i++)
    	{
    		MMF(q);
    		int cnt = 0;
    		int flag = 0;
    		for(int j = 1; j <= len; j++)
    		{
    			if(j > k)
    				cnt = (cnt - q[j - k] + 10) % 10;
    			if((q[j] + s[j] - '0' + cnt) % 10 != i && j + k - 1 > len)
    			{
    				flag = 1;
    				break;
    			}
    			q[j] = (i - (q[j] + 10 + s[j] - '0' + cnt)%10 + 10) % 10;
    			cnt = (cnt + q[j]) % 10;
    			//cout << i<<j<< k<<endl;
    		}
    		if(!flag)
    			return 1;
    	}
    	return 0;
    }
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%s", s + 1);
    		int x = strlen(s + 1);
    		int ans = 1;
    		for(int i = x; i >= 1; i--)
    		{
    			if(check(i))
    			{
    				ans = i;
    				break;
    			}
    		}
    		printf("%d
    ", ans);
    	}
        return 0;
    }

    J 贪心 离散化大小,存数量,排序,从前往后比较,如果一种糖果不够分,只能用下一种糖果,且下个年龄也要从下种糖果开始枚举

     /** @Date    : 2017-09-01 15:59:40
      * @FileName: D.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int vis[1010][1010];
    int dp[1010];
    char a[1010];
    int n, k;
    
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%d%d", &n, &k);
    		scanf("%s", a + 1);
    		MMF(vis);
    		for(int i = 1; i <= n; i++)
    		{
    			for(int j = i + 1; j <= n; j++)
    			{
    				if(a[j] == a[j - 1] || vis[i][j - 1])
    					vis[i][j] = 1;
    				else vis[i][j] = 0;
    			}
    			vis[i][i] = 1;
    		}
    
    
    		MMI(dp);
    		dp[1] = 0;
    		for(int i = 1; i < n; i++)
    		{
    			for(int j = 1; j <= k; j++)
    			{
    				if(j + i <= n && vis[i][i + j - 1])
    					dp[i + j] = min(dp[i] + 1, dp[i + j]);
    			}
    		}
    		int mi = INF;
    		for(int i = n - k + 1; i <= n; i++)
    		{
    			if(vis[i][n])
    				mi = min(mi, dp[i]);
    		}
    		printf("%d
    ", mi);
    	}
        return 0;
    }

    K 水 问k能不能由序列里不同下标的两个数相乘而得...

     /** @Date    : 2017-09-01 13:07:44
      * @FileName: K.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int vis[N];
    int n, k;
    int main()
    {
    	int T;
    	cin >> T;
    	while(T--)
    	{
    		scanf("%d%d", &n, &k);
    		MMF(vis);
    
    		for(int i = 0; i < n; i++)
    		{
    			int x;
    			scanf("%d", &x);
    			vis[x]++;
    		}
    		int ans = -1;
    		for(int i = 1; i <= k; i++)
    		{
    			if(k % i == 0 && vis[i] && vis[k / i])
    			{
    				if(i == k / i && vis[i] < 2)
    					continue;
    				ans = i;
    				break;
    			}
    		}
    		if(ans > 0)
    			printf("%d %d
    ", ans, k / ans);
    		else printf("-1
    ");
    	}
        return 0;
    }

    L D题的加强版,普通O n^2不能满足,考虑使用单调队列优化DP

  • 相关阅读:
    【知识强化】第六章 查找 6.4 散列(Hash)表
    【知识强化】第七章 排序 7.5 归并排序和基数排序
    【知识强化】第六章 查找 6.3 B树和B+树
    【知识强化】第五章 图 5.4 图的应用
    【知识强化】第五章 图 5.3 图的遍历
    linux的自启动服务脚本的(/etc/rc.d/init.d或者其链接/etc/init.d)
    shell文件包含
    shell输入输出重定向
    shell函数参数
    shell函数
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/7465964.html
Copyright © 2011-2022 走看看