CF每日5题Day1(1400)

纯萌新 开盲盒式过水题 每日挑战记录以训练督促自己

1- 479C

纯水

#include 
#define forr(i,l,r) for(int i=l;i<=r;i++)
#define int long long
using namespace std;
const int N=1e5+10;
struct exm{
    int l,r;
    bool operator<(exm const &x)const{
        return (l==x.l?r<x.r:l<x.l);
    }
}a[N];
signed main() {
    int n;
    cin>>n;
    forr(i,1,n){
        cin>>a[i].l>>a[i].r;
    }
    sort(a+1,a+n+1);
    int ed=a[1].r;
    forr(i,2,n){
        if(a[i].r<ed){
            ed=a[i].l;
        }else ed=a[i].r;
    }
    cout<<ed;
    return 0;
}

2-1932D 模拟 STL

首先我们将非王牌花色的每种花色两两配对。
此时可能会剩下一些牌,再把这些牌和王牌花色配对。
最后把剩下的王牌花色两两配对。
并且每牌只有一张 不会有一模一样的牌

我的思路和题解大致相同
但是样例3给我wa红温了

const int N=2e5+10;
string a[N];
void solve(){
    // memset(a,"",sizeof a);
    int n;cin>>n;
    char tr;
    cin>>tr;
    vector<int>pr(2*n+5,0);
    vector<pair<int,int>>ans;
    forr(i,1,2*n){
        cin>>a[i];
    }
    sort(a+1,a+2*n+1,[&](string x,string y){
        if(x[1]==y[1])return x[0]>y[0];
        else if(x[1]==tr)return x[1]==tr;
        else return x[1]>y[1];
    });//排序 
    int trnum=0;//记录王牌的位置 经过排序 王牌一定在前面
    forr(i,1,2*n){
        if(pr[i])continue;
        if(a[i][1]==tr){trnum=i;}
        else{
            if(i+1<=2*n&&a[i][1]==a[i+1][1]&&a[i][0]>a[i+1][0]){
                pr[i]=pr[i+1]=1;
                ans.push_back({i+1,i});
            }
            else if(trnum){
                pr[i]=1,pr[trnum]=1;
                ans.push_back({i,trnum});
                trnum--;
            }
        }
    }
    forr(i,1,2*n){
        if(i+1<=2*n&&a[i][1]==tr&&a[i+1][1]==tr&&a[i][0]>a[i+1][0]&&!pr[i]&&!pr[i+1]){
            pr[i]=pr[i+1]=1;
            ans.push_back({i+1,i});
        }
        if(!pr[i]){
            return cout<<"IMPOSSIBLE"<<endl,void();
        }
    }
    for(auto i:ans){
        cout<<a[i.first]<<' '<<a[i.second]<<endl;
    }
}

之后我发现没有按花色分组,排序花色很麻烦,于是重构代码,分组。

const int N=2e5+10;
map<char,int>idx={{'S',0},{'D',1},{'C',2},{'H',3}};
void solve(){
    int n;cin>>n;
    char tr;
    cin>>tr;
    vector<vector<string>>cd(5);
    vector<pair<string,string>>ans;
    forr(i,1,2*n){
        string a;cin>>a;
        cd[idx[a[1]]].push_back(a);
    }
    forr(i,0,3){
        sort(cd[i].begin(),cd[i].end(),[](string x,string y){
            return x>y;
        });
    }
    int id=idx[tr];
    forr(i,0,3){
        if(i==id)continue;
        int len=cd[i].size();
        //先处理同组配对
        while(cd[i].size()>=2){
            ans.push_back({cd[i][1],cd[i][0]});
            cd[i].erase(cd[i].begin());
            cd[i].erase(cd[i].begin());
        }
        //同组的处理完 再和王牌配对
        while(!cd[i].empty()){
            // cout<
            if(cd[id].empty())return cout<<"IMPOSSIBLE"<<endl,void();
            ans.push_back({cd[i][0],cd[id][0]});
            cd[id].erase(cd[id].begin());
            cd[i].erase(cd[i].begin());
        }
    }
    //其他的配完了 看王牌剩下的部分
    while(cd[id].size()>=2){
        ans.push_back({cd[id][1],cd[id][0]});
        cd[id].erase(cd[id].begin());
        cd[id].erase(cd[id].begin());
    }
    forr(i,0,3){
        if(cd[i].size())return cout<<"IMPOSSIBLE"<<endl,void();
    }
    for(auto i:ans){
        cout<<i.first<<' '<<i.second<<endl;
    }
}
/*
3
2
S
5S 9D 6D 9C
1
S
5H 2C
1
C
8D 8C
*/

调了很长时间,对stl的掌握还不熟练

3-1696C 构造

思路参考

  • 两个操作 一个合并 一个分解 是互逆的 两个数组可以双向转化
    • A → A ′ A\rightarrow A' AA B → B ′ B\rightarrow B' BB 两个数组做操作一 尽量分解到最小 如果 A ′ = B ′ A'=B' A=B 那么 A ′ → B A'\rightarrow B AB 那么就可以 A → B A\rightarrow B AB
  • 再看数据范围 分解后最多能分出5e8个数 很多 需要去重
    • 每个数除m以分解到最小 设 a i a_i ai分到最小是 s i s_i si 那么 a i = s i m t i a_i=s_i m^{t_i} ai=simti a i a_i ai能分解出 m t i m^{t_i} mti个数
    • 用结构体记录 s i , t i s_i,t_i si,ti 比较即可
struct spl{
    int s,t;
};
void solve(){//1696C
    int n,m,k,sum=0;
    cin>>n>>m;
    vector<spl>a,b;
    forr(i,1,n){
        int ai;
        cin>>ai;
        sum+=ai;
        int ti=1;
        while(ai%m==0){
            ai/=m;
            ti*=m;
        }
        if(a.size()>=1&&ai==a.back().s){//去重 分解得到的数相同就合并
            int len=a.size();
            a[len-1].t+=ti;
        }
        else a.push_back({ai,ti});
    }

    cin>>k;
    forr(i,1,k){
        int bi;cin>>bi;
        sum-=bi;
        int ti=1;
        while(bi%m==0){
            bi/=m;
            ti*=m;
        }
        if(b.size()>=1&&bi==b.back().s){
            int len=b.size();
            b[len-1].t+=ti;
        }
        else b.push_back({bi,ti});
    }
    //判断
    if(sum||a.size()!=b.size())return cout<<"NO"<<endl,void();
    int len=a.size();
    forr(i,0,len-1){
        // cout<
        if(a[i].s!=b[i].s||a[i].t!=b[i].t)return cout<<"NO"<<endl,void();
    }
    cout<<"Yes"<<endl;
}

4-1253B 模拟

模拟水题 注意判断好每个人的状态

map<int,int>m;
void solve(){
   m.clear();
   int n;cin>>n;
   vector<int>a(n+1);
   forr(i,1,n)cin>>a[i];
   int jud=0,cnt=0;
   vector<int>ans;
   forr(i,1,n){
       jud+=a[i];
       cnt++;//记录每段长度
       if(jud==0){//判断可以分段了
           ans.push_back(cnt);
           m.clear();
           cnt=0;
           continue;
       }
       //来了 但已经来过  ||  走了 但还没来 (伪人?
       if((a[i]>0&&m.count(a[i]))||(a[i]<0&&m.count(-a[i])==0))return cout<<-1<<endl,void();
       if(a[i]>0)m[a[i]]=1;//来了
       if(a[i]<0)m[a[i]]=2;//走了 记录状态
   }
   for(auto i:m){//还有没回去的
       if(i.second==1)return cout<<-1<<endl,void();
   }
   if(cnt)ans.push_back(cnt);
   cout<<ans.size()<<endl;
   for(auto i:ans){
       cout<<i<<' ';
   }cout<<endl;
}
/*样例
1.来了两次
6
2 5 -5 5 -5 -2
2.没出去
4
1 -1 9 4
3.重复来
4
1 1 -1 -1
4.没来就出去
4
-2 -2 2 -2
*/

5-1263B

很水的构造

  • 注意改了之后不能和其他的pin重复
  • 数据量不大 直接枚举
void solve(){//1263B
   int n;cin>>n;
   map<string ,vector<int>>cnt;
   vector<string>p(n+1);
   forr(i,1,n){
       cin>>p[i];
       cnt[p[i]].push_back(i);
   }
   int ans=0;
   for(auto &i:cnt){
       string tp=i.first;
       int cg=tp[3]-'0';
       while(i.second.size()>1){
           
           int id=i.second[0];
           cg=(cg+1)%10;
           tp[3]=cg+'0';//枚举找怎么改
           // cout<
           if(cnt.count(tp)==0){
               p[id]=tp;//改成功了 放进去
               ans++;
               i.second.erase(i.second.begin());
           }
       }
   }
   cout<<ans<<endl;
   forr(i,1,n){
       cout<<p[i]<<endl;
   }
}

你可能感兴趣的:(codeforce练习,算法,学习)