hey_left 5 Codeforces Round 898 (Div. 4) 续

题目链接

F.

先把序列分割成一个个满足条件的子序列
然后二分长度,去判断子序列是否满足长度,若有一个满足,这个答案可行,判断更长的长度

debug:
存下的子序列忽略了单个元素,单个元素也是一个子序列,把每个元素单独作为一个子序列后可以ac

题解有更简单的做法,双指针,直接遍历一遍得到答案

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N=2e5+10;
int fruit[N],height[N];
int pre[N];
void solve(){
    int n,k;cin>>n>>k;
    vector<pair<int,int>>tmp;
    vector<vector<pair<int,int>>>v;
    for(int i=1;i<=n;i++){
        cin>>fruit[i];
        pre[i]=pre[i-1]+fruit[i];
    }
    for(int i=1;i<=n;i++){
        cin>>height[i];
        tmp.push_back({height[i],i});
        v.push_back(tmp);
        tmp.clear();
    }
    int flag=0;
    for(int i=2;i<=n;i++){
        if(height[i-1]%height[i]==0){
            if(flag==0){
                flag=1;
                tmp.push_back({height[i-1],i-1});
            }
            tmp.push_back({height[i],i});
        }else {
            flag=0;
            if(tmp.size()) {
                v.push_back(tmp);
                tmp.clear();
            }
        }
        if(i==n){
            if(tmp.size())v.push_back(tmp);
        }
    }
//    for(auto t:v){
//        for(int i=0;i<t.size();i++){
//            cout<<t[i].first<<' ';
//        }
//        cout<<'\n';
//    }
    int l=1,r=n,mid;
    bool success=0;
    int ans=0;
    while(l<=r){
        success=0;
        mid=(l+r)/2;
        int sum=0;
        for(int i=0;i<v.size();i++){
            for(int j=0;j+mid-1<v[i].size();j++){
                sum=pre[v[i][j+mid-1].second]-pre[v[i][j].second-1];
                if(sum<=k){
                    success=1;
                    break;
                }
            }
            if(success==1)break;
        }
        if(success==1){
            l=mid+1;
            ans=max(ans,mid);
        }else r=mid-1;
    }
    cout<<ans<<'\n';
}

signed main(){
    int hey_left=1;
    cin>>hey_left;
    while(hey_left--){
        solve();
    }
}

G.

AB-BC,可以发现,消掉一个B,又补上一个B,若是AAAAB形式,一个B可以消掉前面所有的A,同时因为后面一个C,它就只能向前拓展,无法向后拓展
BA-CB,同理,只能向后拓展,无法向前拓展
若是AAABAA型的,那么要考虑B往哪一个方向拓展
绕了一些弯子,其实很简单
若以B开头或结尾,那么一定可以消掉所有的A
只有两头都是A的时候才要继续考虑
若中间出现了连续的大等于两个以上的B,那么也可以全部消掉(一个B拓展一边)
若没有则所有的a的数量-最小的连续a的长度即为答案(一定会剩下一段连续的a,让贡献最小的不被拓展即可)

#include <bits/stdc++.h>
using namespace std;

void solve(){
    string s;cin>>s;
    int cnt_a=0;
    int cnt_b=0;
    int ma=0;
    int mi_a=0x3f3f3f3f,tmp_a=0;
    for(int i=0;i<s.size();i++){
        if(s[i]=='A'){
            tmp_a++;
            cnt_a++;
            ma=max(ma,cnt_b);
            cnt_b=0;
        }
        if(s[i]=='B'){
            cnt_b++;
            mi_a=min(mi_a,tmp_a);
            tmp_a=0;
        }
        if(i==s.size()-1){
            mi_a=min(mi_a,tmp_a);
        }
    }
    if(s[0]=='B'||s[s.size()-1]=='B'){
        cout<<cnt_a<<'\n';
        return ;
    }
    if(ma>=2){
        cout<<cnt_a<<'\n';
    }else{
        cnt_a-=mi_a;
        cout<<cnt_a<<'\n';
    }
}

signed main(){
    int hey_left=1;
    cin>>hey_left;
    while(hey_left--){
        solve();
    }
}

H.

n个点n条边且联通,那么图里有且仅有一个环
若a,b两点在环上,那么a永远追不上b
考虑不都在换上的情况
那么b最优是想跑到环上去,那么a就要阻止它

有一个点事自己没想到的:
b进入环的那个点tag是唯一的,不然就不止一个环了
然后分别算出a,b到tag的距离,若a的小等于b的,那么是NO,否则为YES

还有一个特判:
若a,b在同一个位置,那么一定是NO(都在环上也不行)

学到用拓扑找环:拓扑完后,剩下的度为正数的点一定在环上

找距离用的dij

#include <bits/stdc++.h>
using namespace std;

const int N=2e5+10;
int n,a,b;
vector<int>g[N];
int rd[N];
int tag;
void top_sort(){
    queue<int>q;
    for(int i=1;i<=n;i++){
        if(rd[i]==1)q.push(i);
    }
    while(q.size()){
        int k=q.front();q.pop();
        rd[k]--;
        for(int i=0;i<g[k].size();i++){
            rd[g[k][i]]--;
            if(rd[g[k][i]]==1){
                q.push(g[k][i]);
            }
        }
    }
}

void find_tag(int u,int fa){
    if(rd[u]>0){
        tag=u;
        return ;
    }
    for(int i=0;i<g[u].size();i++){
        int y=g[u][i];
        if(y==fa)continue;
        find_tag(y,u);
    }
}
int vis[N],dist[N];
void init(){
    for(int i=1;i<=n;i++){
        g[i].clear();
        rd[i]=0;
    }
}
void dij(){
    for(int i=1;i<=n;i++){
        dist[i]=0x3f3f3f3f;
        vis[i]=0;
    }
    dist[tag]=0;
    vis[tag]=1;
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    q.push({0,tag});
    while(q.size()){
        auto t=q.top();q.pop();
        vis[t.second]=1;
        int distance=t.first,ver=t.second;
        for(int i=0;i<g[ver].size();i++){
            int k=g[ver][i];
            if(vis[k])continue;
            if(dist[k]>distance+1){
                dist[k]=distance+1;
                q.push({dist[k],k});
            }
        }
    }
}
void solve(){
    init();
    cin>>n>>a>>b;
    for(int i=1,u,v;i<=n;i++){
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
        rd[u]++;rd[v]++;
    }
    if(a==b){
        cout<<"NO"<<'\n';
        return ;
    }
    top_sort();
    if(rd[a]>0&&rd[b]>0){
      //  cout<<rd[a]<<' '<<rd[b]<<'\n';
        cout<<"YES"<<'\n';
        return ;
    }
    find_tag(b,0);
//    for(int i=1;i<=n;i++){
//        if(rd[i]>0)
//    }
    //cout<<tag<<'\n';
    dij();
    if(dist[a]<=dist[b]){
        cout<<"NO"<<'\n';
    }else cout<<"YES"<<'\n';
    //cout<<dist[a]<<' '<<dist[b];
}

signed main(){
    int hey_left=1;
    cin>>hey_left;
    while(hey_left--) {
        solve();
    }
    return 0;
}
posted @ 2024-01-17 19:35  WW爆米花  阅读(3)  评论(0编辑  收藏  举报