听说PAT可能可以抵浙软机试,于是一小时速通PAT甲级(笑
题目名字不记得,就不写了。
数轴上若干个点,给一个长度,求这个长度最多能框住多少点并求出此时这个长度左端点的最小值。排序后双指针一下就行。 O ( n log n ) \mathcal{O}(n\log n) O(nlogn)
#include
typedef long long ll;
const int MAXN = 1e5 + 10;
int a[MAXN];
int main()
{
int n, h; scanf("%d%d", &n, &h);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
std::sort(a + 1, a + 1 + n);
int ans = 0, l;
for (int i = 1, j = 0; i <= n; ++i)
{
while (j + 1 <= n && a[j + 1] - a[i] <= h) ++j;
if (j - i + 1 > ans) ans = j - i + 1, l = a[j] - h;
}
printf("%d %d\n", l, ans);
return 0;
}
给一个数组,问这个数组是否可以通过某个数组快排两趟后得到。注意到pivot有一个很显然的性质即右边的数都大于等于它,左边的数都小于等于它。因此从前往后扫一趟最大值,从后往前扫一趟最小值,若某个位置的最大值和最小值都等于本身则说明这个位置可以成为pivot。统计一下这种数的个数,如果大于等于3则可以。注意特判边界,如果一个pivot是边界的话则剩下只要一个就行。 O ( n ) \mathcal{O}(n) O(n)
#include
typedef long long ll;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int a[MAXN], l[MAXN], r[MAXN];
int main()
{
int t; scanf("%d", &t);
while (t--)
{
int n; scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
int mini = INF;
for (int i = n; i >= 1; --i)
{
mini = std::min(mini, a[i]);
r[i] = mini;
}
int maxi = -INF;
for (int i = 1; i <= n; ++i)
{
maxi = std::max(maxi, a[i]);
l[i] = maxi;
}
int ans = 0, f = 0;
for (int i = 1; i <= n; ++i)
{
if (r[i] == a[i] && l[i] == a[i])
{
++ans;
if (i == 1 || i == n) ++f;
}
}
if (ans + f >= 3) printf("Yes\n");
else printf("No\n");
}
return 0;
}
没啥好说的,按题意模拟一下。
#include
typedef long long ll;
const int MAXN = 1e4 + 10, MAXM = 1e2 + 10;
int lst[MAXN][MAXM];
int m[MAXN], din[MAXN], dout[MAXN];
int main()
{
int n, t; scanf("%d%d", &n, &t);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &m[i]);
for (int j = 1; j <= m[i]; ++j)
{
scanf("%d", &lst[i][j]);
din[lst[i][j]]++; dout[i]++;
}
}
std::vector < int > oli;
for (int i = 1; i <= n; ++i)
if (din[i] >= dout[i] * t)
oli.push_back(i);
memset(din, 0, sizeof din);
for (auto &i : oli)
{
for (int j = 1; j <= m[i]; ++j)
++din[lst[i][j]];
}
int ans = 0;
for (auto &i : oli)
ans = std::max(ans, din[i]);
int cnt = 0;
for (auto &i : oli)
if (din[i] == ans)
{
if (cnt++) printf(" %d", i);
else printf("%d", i);
}
return 0;
}
给二叉树中序和前序遍历,输出后续遍历,同时判断这棵二叉树的类型。建树典中典,建出来之后模拟判断一下就可以,也没什么说的,只不过模拟稍微有点难写。我写得很丑。
#include
typedef long long ll;
const int MAXN = 2e3 + 10;
int l[MAXN], r[MAXN], v[MAXN], id[MAXN], idx, root;
int a[MAXN], b[MAXN];
int depth[MAXN];
std::vector < int > post;
int build(int al, int ar, int bl, int br)
{
if (al > ar) return -1;
if (bl > br) return -1;
int now = ++idx;
v[now] = b[bl];
int i = al;
std::set < int > st;
for ( ; i <= ar; ++i)
{
if (a[i] == v[now])
break;
st.insert(a[i]);
}
int j = bl + 1;
for ( ; j <= br; ++j)
if (st.find(b[j]) == st.end())
break;
l[now] = build(al, i - 1, bl + 1, j - 1);
r[now] = build(i + 1, ar, j, br);
return now;
}
void scan(int now)
{
if (now == -1) return;
scan(l[now]); scan(r[now]);
post.push_back(v[now]);
}
int main()
{
int n; scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i)
scanf("%d", &b[i]);
root = build(1, n, 1, n);
scan(root);
// for (int i = 1; i <= idx; ++i)
// printf("%d %d %d\n", v[i], l[i], r[i]);
std::queue < int > que;
que.push(root);
while (!que.empty())
{
int i = que.front(); que.pop();
if (l[i] != -1) depth[l[i]] = depth[i] + 1, que.push(l[i]);
if (r[i] != -1) depth[r[i]] = depth[i] + 1, que.push(r[i]);
}
bool f = 0;
int d = -1, tot = 0;
for (int i = 1; i <= idx; ++i)
if (l[i] == -1 && r[i] == -1)
{
if (d == -1) d = depth[i];
else if (depth[i] != d) f = 1;
}
else ++tot;
if (!f && tot == (1 << d) - 1) printf("1\n");
else
{
d = -1;
for (int i = 1; i <= idx; ++i)
d = std::max(d, depth[i]);
int td = -1; f = 0; tot = 0;
for (int i = 1; i <= idx; ++i)
{
if (depth[i] == d - 1 || (l[i] == -1 && r[i] == -1 && depth[i] != d))
{
if (td == -1) td = depth[i];
else if (depth[i] != td) f = 1;
}
if (depth[i] != d) ++tot;
}
if (f || tot != (1 << td + 1) - 1) printf("0\n");
else
{
id[root] = 1;
std::queue < int > que;
que.push(root);
while (!que.empty())
{
int i = que.front(); que.pop();
if (l[i] != -1) id[l[i]] = id[i] * 2, que.push(l[i]);
if (r[i] != -1) id[r[i]] = id[i] * 2 + 1, que.push(r[i]);
}
// for (int i = 1; i <= idx; ++i)
// printf("%d ", id[i]);
// printf("\n");
std::vector < int > x;
for (int i = 1; i <= idx; ++i)
if (depth[i] == d)
x.push_back(i);
std::sort(x.begin(), x.end(), [&](int a, int b){
return id[a] < id[b];
});
if (id[x[0]] != 1ll << d) printf("3\n");
else
{
for (int i = 1; i < x.size(); ++i)
if (id[x[i]] - 1 != id[x[i - 1]])
{
printf("3\n");
goto NXT;
}
printf("2\n");
NXT:;
}
}
}
for (int i = 0; i < post.size(); ++i)
if (i) printf(" %d", post[i]);
else printf("%d", post[i]);
return 0;
}
PAT什么时候能加SPJ啊,天天PE,人麻了。
最近在忙保研,928之后大概会写一篇小作文。
以及最近出的题比较多,大概等今年迎新赛或者绍兴那边的比赛供题结束后会专门开篇文章写一下出的题。