今天的封面是水母猫猫和佩佩,原图在这里,记得关注画师夏狩大大
至此,天鹅完成了连续四场比赛在四个不同比赛上四次分的壮举!(ABC388,CodeChef169,牛客月赛109,CF997)
这场难度很有问题啊,D题断层太大了吧,不过还好我前面写得快,真就手速场
A - Shape Perimeter
题意
有一张大小为 m × m m\times m m×m的印章,然后一开始在 ( 0 , 0 ) (0,0) (0,0)的位置(但是没盖下去),然后进行了 n n n次移动,每次两个方向移动的距离告诉你,让你求最后盖出来的这个图案的总周长。
思路
注意到数据范围里面说了 x i x_i xi 和 y i y_i yi ( 1 ≤ x i , y i ≤ m − 1 1 \le x_i, y_i \le m - 1 1≤xi,yi≤m−1) ,也就是每次移动的范围不大于边长,所以最后的图形一定是连起来的,用我们小学二年级就学过的求楼梯型周长可以知道只需要平移边转化为长方形就可以了
如图,算蓝线周长即可
代码
//
// Created by Swan416 on 2025-01-17 22:29.
//
#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n,m;
scanf("%d%d",&n,&m);
int dx,dy;
int x,y;
scanf("%d%d",&dx,&dy);
x=dx,y=dy;
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
x+=a;
y+=b;
}
x+=m;
y+=m;
int ans=(x-dx+y-dy)*2;
printf("%d\n",ans);
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
B - Find the Permutation
题意
构造一个排列 p p p,使得按照以下操作依据这个排列得出的图是给定的无向图:
- 对于每一组整数 1 ≤ i < j ≤ n 1 \le i < j \le n 1≤i<j≤n 当且仅当 p i < p j p_i < p_j pi<pj 时给 p i p_i pi 和 p j p_j pj 连一条边。
思路
如果你是参加了学校寒假集训的新生,那这道题可以让你直观感受到实际XCPC题目和所谓板子题的区别在哪里,我们集训的第一天就写过这样一道题 HDU - 1285 确定比赛名次 ,这题就是典型的板子题,因为题目基本上算是明确告诉你这题需要使用拓补排序这样一个算法
但是这题同样其实也算是拓补排序板子吧也是拓补排序,条件给的要隐晦很多,我们想,
i
<
j
i<j
i<j 是不是就是一个先后顺序关系,然后前者小于后者才会建一条边,那这个边其实就是上面那题里面拓补排序的条件嘛,想通这一点我们直接敲一个拓补排序就行了
代码
//
// Created by Swan416 on 2025-01-17 22:45.
//
#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void solve()
{
int n;
scanf("%d",&n);
vector<string> G(n+1);
for(int i=1;i<=n;i++)
{
cin>>G[i];
G[i]="#"+G[i];
}
vector<pii> edge;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(G[i][j]=='1')
{
edge.emplace_back(i,j);
}
else
{
edge.emplace_back(j,i);
}
}
}
// 拓补排序
vector<int> in(n+1,0);
for(auto [u,v]:edge)
{
in[v]++;
}
queue<int> q;
for(int i=1;i<=n;i++)
{
if(in[i]==0)
{
q.push(i);
}
}
vector<int> ans;
while(!q.empty())
{
int u=q.front();
q.pop();
ans.push_back(u);
for(auto [v,w]:edge)
{
if(v==u)
{
in[w]--;
if(in[w]==0)
{
q.push(w);
}
}
}
}
if(ans.size()!=n)
{
printf("-1\n");
return;
}
for(auto x:ans)
{
printf("%d ",x);
}
printf("\n");
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
C - Palindromic Subsequences
题意
构造一个数组,使得其中的最长回文子串的个数大于 n n n
思路
看样例1,直接就已经把构造方法给你了,我们两个1把其他数夹在中间,然后最右边再补一个2贡献几个答案就出来了
代码
//
// Created by Swan416 on 2025-01-17 22:53.
//
#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
// 6 -> 1 1 2 3 1 2
// 7 -> 1 1 2 3 4 1 2
// 8 -> 1 1 2 3 4 5 1 2
// 9 -> 1 1 2 3 4 5 6 1 2
// 10 -> 1 1 2 3 4 5 6 7 1 2
// 11 -> 1 1 2 3 4 5 6 7 8 1 2
void solve()
{
int n;
scanf("%d",&n);
printf("1 ");
for(int i=1;i<=n-3;i++)
{
printf("%d ",i);
}
printf("1 2\n");
}
int main()
{
int T=1;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}