非常水的手速赛,大部分题都是没有算法的。巨慢手速,老年思维。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