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]);
        }
    }


}