P1229 遍历问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
分析:
首先我们要找到它的子节点只有一个的这种节点,假设有n个,而中序遍历的种数就是2的n次。
代码:
#include <stdio.h>
#include <string.h>
int main()
{
char q[1000],h[1000];
int s=1;
scanf("%s%s",q,h);
for(int i=0;i<strlen(q);i++)
{
for(int j=0;j<strlen(h);j++)
{
if(q[i]==h[j]&&q[i+1]==h[j-1]&&i+1<strlen(q)&&j-1>=0)
s*=2;
}
}
printf("%d\n",s);
return 0;
}
P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
分析:
- 知道并查集的模板;
- 当 Zi=1 时,将 Xi 与 Yi 所在的集合合并。
- 当 Zi=2 时,输出 Xi 与 Yi 是否在同一集合内,是的输出
Y
;否则输出N
。
代码:
#include <stdio.h>
int a[10001],m,n;
int geta(int b)
{
if(a[b]==b)
return b;
else
{
a[b]=geta(a[b]);
return a[b];
}
}
int main()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
a[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
if(z==1)
a[geta(x)]=geta(y);
else
{
if(geta(x)==geta(y))
printf("Y\n");
else
printf("N\n");
}
}
return 0;
}
P2078 朋友 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
分析:
- 并查集的模板题
- 使用并查集分别找出小明和小红的盆友各有多少(包括自己),朋友少的也就是可以组成情侣的数量
代码:
#include <stdio.h>
int a[100000],b[100000],m,n,q,p,c=0,d=0;
int geta(int r)
{
if(a[r]==r)
return r;
else
{
a[r]=geta(a[r]);
return a[r];
}
}
int getb(int r)
{
if(b[r]==r)
return r;
else
{
b[r]=getb(b[r]);
return b[r];
}
}
int main()
{
int x,y,z;
scanf("%d%d%d%d",&n,&m,&p,&q);
for(int i=1;i<=n;i++)
a[i]=i;
for(int i=1;i<=m;i++)
b[i]=i;
for(int i=1;i<=p;i++)
{
scanf("%d%d",&x,&y);
a[geta(x)]=geta(y);
}
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
x*=-1;y*=-1;
b[getb(x)]=getb(y);
}
for(int i=1;i<=n;i++)
{
if(geta(i)==geta(1))
c++;
}
for(int i=1;i<=m;i++)
{
if(getb(i)==getb(1))
d++;
}
if(c>d)
printf("%d\n",d);
else
printf("%d\n",c);
return 0;
}
P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
分析:
sushu(int b)
函数用于判断一个整数是否为素数,如果是素数则返回 1,否则返回 0。dfs(int m, int s, int j)
函数是递归函数,用于进行深度优先搜索。其中参数m
表示当前已经选择了几个数字,s
表示当前已经选择的数字的和,j
表示当前可以选择的数字的起始位置。- 在
dfs
函数中,如果已经选择了 k 个数字,则判断它们的和是否为素数,如果是素数,则将方案数 t 加一。- 否则,继续从当前位置开始选择数字,然后递归调用
dfs
函数。main()
函数中,首先读入数组的大小 n 和要选择的数字个数 k,然后读入数组元素。- 调用
dfs(0, 0, 0)
开始深度优先搜索,并输出方案数 t。
代码:
#include<stdio.h>
int n,k,a[25],t;
int sushu(int b)
{
int i;
if(b<2)
return 0;
for(i=2;i*i<=b;i++)
if(b%i==0)
return 0;
return 1;
}
void dfs(int m,int s,int j)
{
int i;
if(m==k)
{
if(sushu(s))
t++;
return;
}
for(i=j;i<n;i++)
dfs(m+1,s+a[i],i+1);
return;
}
int main()
{
int i;
scanf("%d %d",&n,&k);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
dfs(0,0,0);
printf("%d\n",t);
return 0;
}
D - LOWER
题目描述
给定一个长度为 N 的字符串 S,由大写和小写英文字母组成。
让我们对字符串 S 执行 Q 次操作。 第 i 次操作 (1≤i≤Q) 由一个包含两个整数和一个字符的元组 (ti,xi,ci) 表示,具体如下。
- 如果 ti=1,将 S 的第 xi 个字符改为 ci。
- 如果 ti=2,将 S 中所有大写字母转换为小写(不要使用 xi,ci 进行此操作)。
- 如果 ti=3,将 S 中所有小写字母转换为大写(不要使用 xi,ci 进行此操作)。
在执行完 Q 次操作后,输出 S。
约束条件
- 1≤N≤5×105
- S 是一个长度为 N 的字符串,由大写和小写英文字母组成。
- 1≤Q≤5×105
- 1≤ti≤3 (1≤i≤Q)
- 如果 ti=1,那么 1≤xi≤N (1≤i≤Q)。
- ci 是一个大写字母或小写字母。
- 如果 ti=1,那么 xi=0 并且 ci=
'a'
。 - N,Q,ti,xi 都是整数。
输入
输入以以下格式从标准输入给出:
N S Q t1 x1 c1 t2 x2 c2 ⋮⋮ tQ xQ cQ
输出
在一行中输出答案。
示例 1
Inputcopy | Outputcopy |
---|---|
7 AtCoder 5 1 4 i 3 0 a 1 5 b 2 0 a 1 4 Y | atcYber |
初始时,字符串 S 为 AtCoder
。
- 第一次操作将第 4 个字符改为
i
,将 S 变为AtCider
。 - 第二次操作将所有小写字母转换为大写,将 S 变为
ATCIDER
。 - 第三次操作将第 5 个字符改为
b
,将 S 变为ATCIbER
。 - 第四次操作将所有大写字母转换为小写,将 S 变为
atciber
。 - 第五次操作将第 4 个字符改为
Y
,将 S 变为atcYber
。
执行完操作后,字符串 S 变为 atcYber
,因此输出 atcYber
。
分析:
- 第一次看到道题目想到的是边输入边进行判断,而将字符串全变为大写或小写,就得将字符串重新遍历,如果字符长度过长或变得次数过多,就会时间超限
- 看一下题发现这题的内存限制还是比较大的,所以我们先可以将输入都存放在数组里面,但不要开二维数组
- 简单思考一下,可以发现其实我们只要知道最后一次改大小写的地方就行了,前面怎么变不用管
代码:
#include <stdio.h>
int n,t,r;
char s[500001];
int q,a[500001],b[500001];
char c[500001];
int main()
{
scanf("%d",&n);
scanf("%s",s);
scanf("%d",&q);
for(int i=0;i<q;i++)
{
scanf("%d%d %c",&a[i],&b[i],&c[i]);
if(a[i]==2)
t=i;
else if(a[i]==3)
t=i;
}
for(int i=0;i<q;i++)
{
if(i==t)
{
if(a[i]==2)
{
for(int i=0;i<n;i++)
{
if(s[i]>='A'&&s[i]<='Z')
s[i]+=32;
}
}
else if(a[i]==3)
{
for(int i=0;i<n;i++)
{
if(s[i]>='a'&&s[i]<='z')
s[i]-=32;
}
}
}
if(a[i]==1)
{
s[b[i]-1]=c[i];
}
}
printf("%s\n",s);
return 0;
}
P1135 奇怪的电梯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
分析:
dfs,处理好边界就行了
代码:
#include <stdio.h>
int n,a,b,k[201],ans[201];
void dfs(int x,int z)
{
ans[x]=z;
if(x+k[x]<=n&&z+1<ans[x+k[x]])
dfs(x+k[x],z+1);
if(x-k[x]>0&&z+1<ans[x-k[x]])
dfs(x-k[x],z+1);
}
int main()
{
for(int i=1;i<=201;i++)
{
ans[i]=999999;
}
scanf("%d%d%d",&n,&a,&b);
for(int i=1;i<=n;i++)
scanf("%d",&k[i]);
dfs(a,0);
if(ans[b]==999999)
printf("-1\n");
else
printf("%d\n",ans[b]);
return 0;
}