A : 元音回文
问题描述
现在有一个长度为 nn 的字符串,都有小写字母组成。
现在所有元音字母都可以看作相同的字符
输出最长回文子串的长度
一个与自身的逆序相同的字符串即为回文串
比如 aba,aabbaa,asdffdsaaba,aabbaa,asdffdsa 都为回文串
输入格式
第一行一个整数 nn , 1\le n\le50001≤n≤5000,表示字符串长度
接下来一行表示字符串
输出格式
输出一行,一个数,代表答案
样例输入
10
aeioubaeio
样例输出
9
样例解释
所以元音都可以看作相同字符,所以回文串为 eioubaeioeioubaeio
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
map<char,char>has;
char a[5010];
int n;
int getmax1(int k)
{
int ans=1;
int i=k-1;
int j=k+1;
while(i>=0&&j<n)
{
if(a[i]==a[j])
{ans+=2;i--;j++;continue;}
break;
}
return ans;
}
int getmax2(int k)
{
int ans=0;
int i=k;
int j=k+1;
while(i>=0&&j<n)
{
if(a[i]==a[j])
{ans+=2;i--;j++;continue;}
break;
}
return ans;
}
int main()
{
has.insert(make_pair('u','u'));
has.insert(make_pair('e','e'));
has.insert(make_pair('i','i'));
has.insert(make_pair('o','o'));
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
map<char,char>::iterator it;
it=has.find(a[i]);
if(it!=has.end())
a[i]='a';
}
int mmax=0;
for(int i=0;i<n;i++)
{
mmax=max(getmax1(i),mmax);
mmax=max(getmax2(i),mmax);
}
cout<<mmax<<endl;
}
B : 模测成绩单
问题描述
模测结束了,小 L 拿到了一些形如 A 比 B 得分高 的信息,现在小 L 想要输出一份成绩排名表,使得排名表满足得到的信息,并且学号小的尽可能排在前面。
输入格式
第一行有两个整数,n,mn,m 表示有 nn 个同学,第 ii 个同学学号为 ii ,有 mm 条信息。
接下来有 mm 行,每行有两个整数 A,BA,B ,表示学号为 AA 的同学得分比学号为 BB 的同学得分高。
1\le n,m\le 10^61≤n,m≤10
6
1\le A,B\le n1≤A,B≤n
数据保证有解
输出格式
输出一行 nn 个数,表示按照学号给出的排名。
样例输入
5 3
4 5
2 3
1 5
样例输出
1 2 3 4 5
#include <iostream>
#include <queue>
#define N 1000000
using std::priority_queue;
int point[N], nex[N], v[N], in[N];
int mark[N];
int tot = 0;
void add(int x, int y)
{
tot++;
nex[tot] = point[x];
point[x] = tot;
v[tot] = y;
in[y]++;
}
int main()
{
int n, m;
priority_queue<int, std::vector<int>, std::greater<int> > q;
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++)
{
int x, y;
scanf("%d %d", &x, &y);
add(x, y);
}
for (int i = 1; i <= n; i++)
{
if (in[i] == 0)
{
q.push(i);
mark[i] = 1;
}
}
while (!q.empty())
{
int x = q.top();
printf("%d ", x);
q.pop();
for (int i = point[x]; i; i = nex[i])
{
in[v[i]]--;
if (in[v[i]] == 0 && !mark[v[i]])
{
mark[v[i]] = 1;
q.push(v[i]);
}
}
}
printf("\n");
return 0;
}
C : 种酸奶
问题描述
小 L 喜欢喝酸奶,春天来了,小 L 想把酸奶种在地里,等到来年春暖花开,就能长出好多好多酸奶了
有 nn 个坑,小 L 给坑都编上号,从 11 号到 nn 号,每个坑最多种一瓶酸奶。
但是有一些限制形如 k,a,b,ck,a,b,c 。
若 kk 等于 11 ,则第 aa 号坑到第 bb 号坑最多种 cc 瓶酸奶。
若 kk 等于 22 ,则第 aa 号坑到第 bb 号坑最少种 cc 瓶酸奶。
若 kk 等于 33 ,则第 aa 号坑到第 bb 号坑必须种少于 cc 瓶酸奶。
若 kk 等于 44 ,则第 aa 号坑到第 bb 号坑必须种多于 cc 瓶酸奶。
若 kk 等于 55 ,则第 aa 号坑到第 bb 号坑必须种等于 cc 瓶酸奶。
问小 L 最多种多少瓶酸奶
输入格式
第一行两个整数 n,mn,m ,表示有 nn 个坑,有 mm 条限制。
1\le n,m\le10001≤n,m≤1000
接下来 mm 行,每行四个整数 k,a,b,ck,a,b,c
1\le k\le 51≤k≤5 , 1\le a\le b\le n1≤a≤b≤n , |c|<=2000∣c∣<=2000
输出格式
输出一行,若有解则输出一个整数,表示答案
否则输出 impossible
样例输入
5 5
1 1 4 4
2 2 5 1
3 2 4 2
4 1 5 2
5 1 3 2
样例输出
3
#include <iostream>
#include <queue>
#define N 300000
#define INF 99999999
using std::pair;
using std::queue;
using std::make_pair;
int dis[N], v[N], point[N], nex[N], w[N];
int can[N], cnt[N];
int tot = 0;
void add(int x1, int x2, int wi)
{
// x1 + w >= x2
tot++;
nex[tot] = point[x1];
point[x1] = tot;
v[tot] = x2;
w[tot] = wi;
}
bool spfa(int s, int n)
{
queue<int> q;
for (int i = 1; i <= n; i++)
{
dis[i] = INF;
can[i] = 0;
}
dis[s] = 0;
can[s] = 1;
q.push(s);
while (!q.empty())
{
int x = q.front();
q.pop();
for (int i = point[x]; i; i = nex[i])
{
if (dis[v[i]] > dis[x] + w[i])
{
dis[v[i]] = dis[x] + w[i];
cnt[v[i]] = cnt[x] + 1;
if (cnt[v[i]] >= n)
{
return false;
}
if (!can[v[i]])
{
can[v[i]] = 1;
q.push(v[i]);
}
}
}
can[x] = 0;
}
return true;
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++)
{
int k, x, y, wi;
scanf("%d %d %d %d", &k, &x, &y, &wi);
if (k == 1)
add(x, y + 1, wi);
if (k == 2)
add(y + 1, x, -wi);
if (k == 3)
add(x, y + 1, wi - 1);
if (k == 4)
add(y + 1, x, -wi - 1);
if (k == 5)
{
add(x, y + 1, wi);
add(y + 1, x, -wi);
}
}
for (int i = 1; i < n + 1; i++)
{
add(i, i + 1, 1);
add(i + 1, i, 0);
}
bool getted = spfa(1, n + 1);
if (getted)
printf("%d\n", dis[n + 1]);
else
printf("impossible\n");
return 0;
}
D : 信息传递
问题描述
有 nn 个人,每个人都有一个编号,从 11 到 nn 。
如果 AA 得知一个消息,那么他一定会告诉 BB 。
问最少把消息告诉几个人,能让所有人得知这个消息。
输入格式
第一行两个整数 n,mn,m , 1\le n,m\le 10^61≤n,m≤10
6
,表示有 nn 个人
接下来 mm 行,每行给出一个关系形如 A,BA,B ,表示如果 AA 得知一个消息,那么他一定会告诉 BB 。
输出格式
输出一行,一个数,代表答案
样例输入
10 10
1 3
2 4
4 5
2 8
5 2
5 9
6 8
9 2
10 5
5 8
样例输出
4
样例解释
只需要告诉 1,6,7,101,6,7,10 四个人即可
#include <iostream>
#define N 9999999
int l_v[N], l_point[N], l_nex[N];
int l_tot;
int f1[N];
int f1i = 0, f2i = 0;
int f2[N];
int mrk1[N];
int mrk2[N];
int x_v[N];
int x_point[N];
int x_nex[N];
int x_tot;
int ine[N];
void add(int x, int y)
{
l_tot++;
l_nex[l_tot] = l_point[x];
l_point[x] = l_tot;
l_v[l_tot] = y;
}
void addx(int x, int y)
{
x_tot++;
x_nex[x_tot] = x_point[x];
x_point[x] = x_tot;
x_v[x_tot] = y;
}
void dfs1(int v)
{
mrk1[v] = 1;
for (int i = l_point[v]; i; i = l_nex[i])
{
if (!mrk1[l_v[i]])
{
dfs1(l_v[i]);
}
}
f1[++f1i] = v;
}
void dfs2(int v)
{
f2[v] = f2i;
for (int i = x_point[v]; i; i = x_nex[i])
{
if (!f2[x_v[i]])
{
dfs2(x_v[i]);
}
}
}
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d %d", &x, &y);
add(x, y);
addx(y, x);
}
for (int i = 1; i <= n; i++)
{
if (!mrk1[i]) dfs1(i);
}
for (int i = n; i > 0; i--)
{
if (!f2[f1[i]])
{
f2i++;
dfs2(f1[i]);
// printf("%d- %d\n", f2i, f1[i]);
}
}
for (int i = 1; i <= n; i++)
{
// printf("%d %d\n", f1[i], f2[i]);
for (int p = l_point[i]; p; p = l_nex[p])
{
if (f2[i] != f2[l_v[p]])
{
ine[f2[l_v[p]]]++;
}
}
}
// printf("\n");
int count = 0;
for (int i = 1; i <= f2i; i++)
{
if (ine[i] == 0) count++;
}
printf("%d\n", count);
return 0;
}
思路
第一个题在力扣网站上看见过,当时就不会,和这个差不多的用的双指针做的。
好写一点的基础做法用到这个:
链接
第二个需要队列:定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
种酸奶:
先要学会这个
最后一题和例题一样
后面还有个强连通分量的知识
下周题有的话再学学这块。