Codeforces Round #541题解

A题

通过平移线段可以发现其实就是缺少的那一块的大小

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=5e5+10;
int main(){
    ios::sync_with_stdio(false);
    ll a,b,c,d;
    cin>>a>>b>>c>>d;
    cout<<(a+2)*(b+d+2)-d*(a-c)-a*b-c*d<<endl;
    return 0;
}
View Code

B题

思维题,因为我们肯定是最优策略,因此当前两个点的最小值和前面的两个最大值的差值相减,但是要和0取max

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=5e5+10;
int a[N],b[N];
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i;
    for(i=2;i<=n+1;i++)
        cin>>a[i]>>b[i];
    ll ans=1;
    a[1]=b[1]=0;
    n++;
    for(i=1;i<=n;i++){
        ans+=max(0,min(a[i],b[i])-max(a[i-1],b[i-1])+1);
        if(a[i-1]==b[i-1])
            ans--;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

C题

肯定是先递增后递减最好,因为不是这样,最大值无论移到哪里都会变劣

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=5e5+10;
int a[N],b[N];
queue<int> q1;
stack<int> q2;
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i,j,k;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    for(i=1;i<=n;i++){
        if(i&1)
            q1.push(a[i]);
        else
            q2.push(a[i]);
    }
    while(q1.size()){
        cout<<q1.front()<<" ";
        q1.pop();
    }
    while(q2.size()){
        cout<<q2.top()<<" ";
        q2.pop();
    }
    return 0;
}
View Code

D题

这题显然是比较大小的关系,这容易让我们联想到差分约束建图,虽然差分约束不行,但是建图还是很合理的,我们可以考虑将小点连往大点。但是现在有相同点,这个很好处理,只要考虑并查集,把相同点缩成一个点

之后就是个拓扑图跑一下最长路,问题是可能有环,也就是冲突情况,这种情况这些点不会进入拓扑排序,因此只要判断一下是否全部都进行了拓扑排序

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e6+10;
int h[N],ne[N],e[N],idx;
int ans[N];
int p[N];
int in[N];
int vis[N];
int flag;
string s[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int find(int x){
    if(x!=p[x]){
        p[x]=find(p[x]);
    }
    return p[x];
}
void topo(int u){
    queue<int> q;
    ans[u]=1;
    q.push(u);
    while(q.size()){
        int t=q.front();
        q.pop();
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            in[j]--;
            ans[j]=max(ans[j],ans[t]+1);
            if(!in[j]){
                vis[j]=1;
                q.push(j);
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    int i,j;
    for(i=1;i<=n+m;i++){
        p[i]=i;
    }
    memset(h,-1,sizeof h);
    for(i=1;i<=n;i++){
        cin>>s[i];
        s[i]=" "+s[i];
        for(j=1;j<=m;j++){
            if(s[i][j]=='='){
                int pa=find(i);
                int pb=find(n+j);
                if(pa!=pb)
                    p[pa]=pb;
            }
        }
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            int pa=find(i),pb=find(n+j);
            if(s[i][j]=='>'){
                add(pb,pa);
                in[pa]++;
            }
            else if(s[i][j]=='<'){
                add(pa,pb);
                in[pb]++;
            }
        }
    }
    for(i=1;i<=n+m;i++){
        int pa=find(i);
        if(pa==i&&!in[i]&&!vis[i]){
            vis[i]=1;
            topo(i);
        }
    }
    for(i=1;i<=n+m;i++){
        int pa=find(i);
        if(pa==i&&!vis[i]){
            cout<<"No"<<endl;
            return 0;
        }
    }
    cout<<"Yes"<<endl;
    for(i=1;i<=n;i++){
        int pa=find(i);
        cout<<ans[pa]<<" ";
    }
    cout<<endl;
    for(i=n+1;i<=n+m;i++){
        int pa=find(i);
        cout<<ans[pa]<<" ";
    }
    cout<<endl;
    return 0;
}
View Code

E题

想的时候没想到,看到题解觉得顺理成章

主要是观察题目信息,给的信息确实比较明显,因为只考虑单个字符,因此可以使用dp数组记录前i个字符为j的最大子串长度

因为题目要求的是一个当前pi一个之前的串中单个字符之后再一个pi

因此我们仔细观察可以发现前缀和后缀的思路。

之后只要check所有情况取max,注意当当前pi中所有字符相等的时候,要额外考虑,因此其他情况中间都会分割,而这种情况不会,且没有通性。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
ll f[N][30];
string s;
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    int i,j;
    memset(f,0,sizeof f);
    for(i=1;i<=n;i++){
        cin>>s;
        int len=(int)s.size();
        s=" "+s;
        int pre=1;
        for(j=2;j<=len;j++){
            if(s[j]==s[1])
                pre++;
            else
                break;
        }
        int suf=1;
        for(j=len-1;j>=1;j--){
            if(s[j]==s[len]){
                suf++;
            }
            else
                break;
        }
        for(j=0;j<26;j++){
            f[i][j]=(f[i-1][j]>0);
        }
        for(j=1;j<=len;j++){
            int tmp=j;
            while(tmp+1<=len&&s[tmp+1]==s[j])
                tmp++;
            f[i][s[j]-'a']=max(f[i][s[j]-'a'],1ll*tmp-j+1);
            j=tmp;
        }
        if(pre==len){
            f[i][s[1]-'a']=(f[i-1][s[1]-'a']+1)*len+f[i-1][s[1]-'a'];
        }
        else{
            f[i][s[1]-'a']=max(f[i][s[1]-'a'],1ll*pre+1ll*(f[i-1][s[1]-'a']>0));
            f[i][s[len]-'a']=max(f[i][s[len]-'a'],1ll*suf+1ll*(f[i-1][s[len]-'a']>0));
            if(s[1]==s[len]&&f[i-1][s[1]-'a']){
                f[i][s[1]-'a']=max(f[i][s[1]-'a'],1ll*pre+suf+1);
            }
        }
    }
    ll ans=0;
    for(i=0;i<26;i++){
        ans=max(ans,f[n][i]);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

F题

能看的出是并查集的思路,有两种做法,一种是启发式合并,一种是维护头结点之后跑dfs

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
int p[N];
int n;
vector<int> num[N];
int find(int x){
    if(x!=p[x]){
        p[x]=find(p[x]);
    }
    return p[x];
}
void dfs(int u){
    int i;
    cout<<u<<" ";
    for(i=0;i<num[u].size();i++){
        int j=num[u][i];
        dfs(j);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    int i;
    for(i=1;i<=n;i++){
        p[i]=i;
    }
    for(i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        int pa=find(a);
        int pb=find(b);
        p[pa]=pb;
        num[pb].push_back(pa);
    }
    for(i=1;i<=n;i++){
        if(p[i]==i){
            dfs(i);
            break;
        }
    }
    return 0;
}
View Code

G题

原文地址:https://www.cnblogs.com/ctyakwf/p/14170448.html