A
题意:给你两个矩形,按照他给你方式摆放,求边界长度(看图就懂了)
题解:直接加减运算搞一下
#include <bits/stdc++.h>
using namespace std;
int main(){
int w1,l1,w2,l2;
long long int ans;
scanf("%d%d%d%d",&w1,&l1,&w2,&l2);
if(w1==w2)ans=l1+l2+w1+w2+l1+l2+4;
else ans=l1+l2+(w1-w2)+l2-1+l1+w1+w2+5;
cout<<ans<<endl;
//while(1)getchar();
return 0;
}
B
题意:按照时间顺序给你比分,让你求最多有多少次平局
题解:从两个时间点的顺序之间直接求平分的次数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int main()
{
ll n;
cin>>n;
ll ans=1,a=0,b=0;
for(int i=0;i<n;i++){
ll x,y;
cin>>x>>y;
if(x==a&&y==b) continue;
if(a>b){
if(x>y){if(y>=a) ans+=y-a+1;}
else ans+=x-a+1;
}
else if(a<b){
if(x<y){if(x>=b) ans+=x-b+1;}
else ans+=y-b+1;
}
else if(a==b){
ans+=min(x,y)-a;
}
a=x,b=y;
}
cout<<ans<<endl;
}
C
题意:把学生排成一个圈 然后同学之间的最大高度差最小
题解:排成中间高 两边低就可以了
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 100+5;
int n,a[maxn];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
for(int i=0;i<n;i++){
if(i%2==0)
printf("%d ",a[i]);
}
for(int i=n-1;i>=0;i--){
if(i%2==1)
printf("%d ",a[i]);
}
}
D
题意:1到n为第一天 1到m 为第二天
矩阵元素aij表示 第i天和第 j天数字之间的关系
让你 构造出这些数字
题解:没有等号直接拓扑排序就行,所以这里等号的需要并查集缩一下点
1-n是第一天 n+1到m是第二天
#include <bits/stdc++.h>
using namespace std;
#define maxn 2500+5
int pre[maxn],in[maxn],ans[maxn];
int n,m;
vector<int>G[maxn];
char a[maxn][maxn];
int Find(int x){return x==pre[x]?x:pre[x]=Find(pre[x]);}
void mix(int x,int y){
int fx=Find(x),fy=Find(y);
if(fx!=fy)pre[fx]=fy;
}
void add_edge(int u,int v){
G[u].push_back(v);
in[v]++;
}
int topo(){
queue<int>q;
for(int i=1;i<=m+n;i++){
if(Find(i)==i&&in[i]==0){
q.push(i);ans[i]=1;
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
in[v]--;
if(in[v]==0){
ans[v]=ans[u]+1;
q.push(v);
}
}
}
for(int i=1;i<=m+n;i++){
if(!ans[Find(i)])return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<=n+m;i++)pre[i]=i;
for(int i=1;i<=n;i++){
scanf("%s",a[i]+1);
for(int j=1;j<=m;j++){
if(a[i][j]=='='){
mix(i,j+n);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='<')add_edge(Find(i),Find(n+j));
else if(a[i][j]=='>')add_edge(Find(n+j),Find(i));
}
}
if(!topo()){
puts("No");
}else {
puts("Yes");
for(int i=1;i<=n;i++){
cout<<ans[Find(i)]<<" ";
}
cout<<endl;
for(int j=n+1;j<=m+n;j++){
cout<<ans[Find(j)]<<" ";
}
}
return 0;
}
F
题意:按照题目给的顺序,这两个元素所属的区块一定是相邻的,让你求出原序列
题解:每个元素都放在一个 rope(别慌,没做这个题之前我也不知道是啥,其实跟vector一样用)
然后如果两个元素不在同一个区块里,就把这两个区块合并,最后的最大的区块就是最后的顺序了
#include <bits/stdc++.h>
#include<ext/rope>
#define INF 0x3f3f3f3f
using namespace __gnu_cxx;
using namespace std;
const int maxn = 150000+5;
int n,pre[maxn];
int t[maxn];
int Find(int x){
return pre[x]==x?x:pre[x]=Find(pre[x]);
}
rope<int>ans[maxn];int flag=0;
int main(){
scanf("%d",&n);
for(int i=01;i<=n;i++)pre[i]=i,ans[i].push_back(i);
for(int i=0;i<n-1;i++){
int x,y;
scanf("%d%d",&x,&y);
int fx=Find(x),fy=Find(y);
ans[fx]+=ans[fy];
pre[fy]=fx;
}
for(int i=1;i<=n;i++){
if(pre[i]==i)
for(int j=0;j<ans[i].size();j++){
printf("%d ",ans[i][j]);
}
}
}