题目大意 :
给你一个数,一次能打印两面,问表示需要打印多少张才能将所有打印完。
析题得侃 :
如果这个数是偶数, 需要打印 n / 2
如果这个数是奇数, 需要打印 n / 2 + 1.
考察点:
签到,思维
Code:
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
int main(void) {
int n;
cin >> n;
if(n & 1) cout << n / 2 + 1 << endl;
else cout << n / 2 << endl;
return 0;
}
题目大意:
给一个 3 * 3 的矩阵,每个位置有一个数,之后再给你一些数,如果这些数在这个矩阵中
并且所以数组合到一起可以使得 有一列或者有一行或者斜对角 都出现过,就输出 Yes,
否则输出 No.
析题得侃:
没有想到好的方法,就一个一个枚举了,hh,方法虽然笨点,总归是 AC 了。
考察点 :
模拟
Code :
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
int a[5][5];
int cnt[5][5];
int main(void) {
for(int i = 1; i <= 3; i ++) {
for(int j = 1; j <= 3; j ++) {
cin >> a[i][j];
}
}
int n,value;
cin >> n;
while(n --) {
cin >> value;
bool vis = false;
for(int i = 1; i <= 3; i ++) {
for(int j = 1; j <= 3; j ++) {
if(a[i][j] == value) {
vis = true;
cnt[i][j] = 1;
break;
}
}
if(vis) break;
}
}
if((cnt[1][1] == 1 && cnt[1][2] == 1 && cnt[1][3] == 1) || (cnt[2][1] == 1 && cnt[2][2] == 1 && cnt[2][3] == 1) ||
(cnt[3][1] == 1 && cnt[3][2] == 1 && cnt[3][3] == 1) || (cnt[1][1] == 1 && cnt[2][1] == 1 && cnt[3][1] == 1) ||
(cnt[1][2] == 1 && cnt[2][2] == 1 && cnt[3][2] == 1) || (cnt[1][3] == 1 && cnt[2][3] == 1 && cnt[3][3] == 1) ||
(cnt[1][1] == 1 && cnt[2][2] == 1 && cnt[3][3] == 1) || (cnt[1][3] == 1 && cnt[2][2] == 1 && cnt[1][3] == 1)
) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
题目大意:
大概就是说给你一个不超过三位的一个数,然后这之后会有一些操作,可以指定某一位是多少,
但是不允许有前导 0 ,同一个位置不能重复指定,否则会出现错误,除了指定的数外,还要保证
最后得到的数是最小的。
析题得侃:
题是不难,就是细节忒多,需要考虑的情况比较多,这道题我还犯了一个小错误,就是重复输出了,
对于某一种情况没有及时跳出来,导致对某一个测试样例会输出两个答案。不过这道题收获还是
蛮多的,重要的是学会尝试着去找不同的情况去接近答案。
考察点:
思维,模拟
Code:
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
int n,m;
int x,b;
int a[4],cnt[4];
int main(void) {
cin >> n >> m;
if(n == 1 && m == 0) {
// 这种情况要及时跳出来,不然就与下面的冲突了
cout << 0 << endl;
return 0;
}
bool vis = true;
while(m --) {
cin >> x >> b;
if(vis == false) continue;
if(n > 1 && x == 1 && b == 0) {
vis = false;
} else if(cnt[x] && a[x] != b) {
vis = false;
} else {
a[x] = b;
cnt[x] = 1;
}
}
if(vis == false) {
cout << -1 << endl;
} else {
for(int i = 1; i <= n; i ++) {
if(a[1] == 0 && cnt[1] == 0) a[1] = 1;
cout << a[i] ;
}
cout << endl;
}
return 0;
}
题目大意:
先给一些关系,表明两个数之间是朋友的关系,接着再给一些关系,表示这些人之间不是朋友的
关系,最后问你每个人可以有多少个人可以是自己的候选朋友(不包括已有的),而且所有人跟
自己还必须是在同一个连通块内的。
析题得侃:
这题是赛后补的,琢磨完第三题剩下的时间就不多了,跟一些大佬真的没法比,不过最后靠自己
的能力把这道题补出来,自己还是很欣慰的。
一看到这道题涉及到关系,第一时间想到的就是并查集,然后就往哪里想,实际上是带权并查集
的初级版,我们最后求得是候选的朋友,我们可以求出这个连通块的大小,然后每个人的朋友就是
当前这个点的出度,还有在同一个连通块中跟这个人也有可能不是朋友,这是我们可以拿一个
cnt 数组用来计算不是朋友的数量(是双向的,具体的会在代码中体现),然后这个连通块的大小
- 朋友数量 - 不是朋友的数量 = 候选朋友的数量(同一个连通块内)。
考察点:
带权并查集,连通块
Code:
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int maxn = 1e5 + 10;
int vis[maxn],cnt[maxn];
int fa[maxn],sz[maxn],deg[maxn];
int ans = 0;
int get(int x) {
return x == fa[x] ? x : fa[x] = get(fa[x]);
}
void Union(int x,int y) {
int xx = get(x);
int yy = get(y);
if(xx == yy) return ;
fa[yy] = xx;
sz[xx] += sz[yy];
return ;
}
int main(void) {
int n,m,k;
int u,v;
cin >> n >> m >> k;
for(int i = 1; i <= n; i ++) {
fa[i] = i;
// 刚开始每个都是独立的,都是一个
sz[i] = 1;
}
for(int i = 1; i <= m; i ++) {
cin >> u >> v;
// 记录每个点的出度
deg[u] ++;
deg[v] ++;
Union(u,v);
}
for(int i = 1; i <= k; i ++) {
cin >> u >> v;
if(get(u) == get(v)) {
// 不是朋友,但在同一个连通块内,所以都需要减少
cnt[u] --;
cnt[v] --;
}
}
for(int i = 1; i <= n; i ++) {
cout << sz[get(i)] - deg[i] + cnt[i] - 1<< " ";
}
return 0;
}
题目大意:
有一串字符,我们可以执行两种操作:
1、替换某个位置的字符
2、查询某一段区间不同字符的个数
析题得侃:
很明显:这道题的两种操作分别是:单点修改,区间查询
是不是跟树状数组的基本操作十分的类似,当然,线段树也是可以的,但是杀鸡焉用牛刀,
关键是自己太菜,哈哈。我们可以用一个二维的数组记录当前位置之前每个字符出现的数量。
具体实现看代码。
考察点:
树状数组,线段树
Code:
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 5e5 + 10;
char a[maxn];
int c[maxn][26];
int t,op,pos,l,r,len;
char v;
int lowbit(int x) {
return x & -x;
}
void insert(int id,int x,int v) {
for(int i = id; i <= len; i += lowbit(i)) {
c[i][x] += v;
}
return ;
}
int query(int id,int x) {
int ans = 0;
// x 代表是( x - 'a')
for(int i = id; i; i -= lowbit(i)) {
ans += c[i][x];
}
return ans;
}
int main(void) {
cin >> len;
scanf("%s",a + 1);
for(int i = 1; i <= len; i ++) {
int v = a[i] - 'a';
insert(i,v,1);
}
cin >> t;
while(t --) {
cin >> op;
if(op == 1) {
cin >> pos >> v;
// 更新
insert(pos,a[pos] - 'a',-1);
insert(pos,v - 'a',1);
a[pos] = v; // 修改后记得修改原数组
} else {
cin >> l >> r;
int res = 0;
for(int i = 0; i < 26; i ++) {
// 如果这个区间有这个字符,只需要 + 一次即可
if(query(r,i) - query(l - 1,i)) res ++;
}
cout << res << endl;
}
}
return 0;
}
待补
后记:
本人能力有限,写的不当之处还望各位看官多多指教,如在参考中遇到各种问题,欢迎大家
留言交流,共同交流。