#797Div3 codeforcesround (A~G题)

G. Count the Trains

Problem - G - Codeforces

思路

思维。不断维护递减序列。

set内保存的是每节火车的头。对于一个修改,如果其前一个id的值比它大那就放入集合s。后面依次排出不符合严格递减序列的元素。复杂度O(mlogn)。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=1e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n,m;
int a[maxn];
void init(/* arguments */) {
    n=rr(),m=rr();
    for(int i=1;i<=n;i++) a[i]=rr();
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        init();

        set<int> s;
        for(int i=1;i<=n;i++) {
            if(s.empty() || a[i]<a[*s.rbegin()]) {
                s.insert(i);
            }
        }
        for(int i=0;i<m;i++) {
            int x=rr(),k=rr();
            a[x]-=k;
            auto it=s.upper_bound(x);
            if(it!=s.begin() && a[*prev(it)]>a[x]) s.insert(x);
            else if(it==s.begin()) s.insert(x);
            while (1) {
                it=s.upper_bound(x);
                if(it==s.end()) break;
                if(a[*it]>=a[x]) s.erase(*it);
                else break;
            }
            std::cout << (int)s.size() << ' ';
        }
        std::cout << '\n';
    }
    return 0;

}

F. Shifting String

Problem - F - Codeforces

思路

画出来就是很多个圈,他们之间能不断右移。最小交换次数就是所有圈的最小右移最小周期数的最小公倍数。思路很好想,主要在于怎么解决。

处理方法上想到dfs,求出圈的序列。然后不断枚举可能性求出最小的右移周期。考虑到最长有200个,就选择循环求出圈的序列。但是又由于不断枚举可能性会导致复杂度过高。问题主要在于如何在O(L)时间内求出最小的右移次数(L为这个圈的长度)。然后想到kmp算法…kmp求最长公共前后缀。但是这是不对的。(痛苦面具)。

然后看了别人的枚举,发现枚举周期只要枚举L的因子就行了,…(沉默了),瞬间恍然大悟。复杂度O(LlogL)。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e2+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n;
int a[maxn],vis[maxn];
string s;
void init(/* arguments */) {
    n=rr();
    cin>>s;
    for(int i=0;i<n;i++) a[i]=rr()-1;
    mem(vis,0);
}
ll gcd(ll a,ll b) {
    while (b^=a^=b^=a%=b);
    return a;
}
ll lcm(ll a,ll b) {
    return a*b/gcd(a,b);
}
bool check(string &b,int t) {
    int L=b.size();
    if(L%t) return 0;
    for(int i=0;i+t<L;i++) {
        if(b[i]!=b[i+t]) return 0;
    }
    return 1;
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        init();

        ll ans=1;
        for(int i=0;i<n;i++) {
            if(vis[i]) continue;
            string t;
            while (!vis[i]) {
                t+=s[i];
                vis[i]=1;
                i=a[i];
            }
            int T=1;
            while (!check(t,T)) T++;
            ans=lcm(ans,T);
        }
        std::cout << ans << '\n';
    }
    return 0;

}

E. Price Maximization

E - Price Maximization

思路

余数能匹配出>=k那么ans+1。

要调用multiset的lower_bound而不能直接调用lower_bound否则超时。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n,k;
int a[maxn];
void init(/* arguments */) {
    n=rr(),k=rr();
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        init();

        multiset<int> s;
        ll ans=0;
        qwe(i,0,n-1) {
            a[i]=rr();
            ans+=(a[i]/k);
            a[i]%=k;
            s.insert(a[i]);
        }
    
        while (!s.empty()) {
            int x=*s.begin();
            s.erase(s.begin());
            // auto it=lower_bound(all(s),k-x);
            auto it=s.lower_bound(k-x);
            if(it!=s.end()) {
                ans++;
                s.erase(it);
            }
        }
        std::cout << ans << '\n';
    }
    return 0;

}

D. Black and White Stripe

D - Black and White Stripe

思路

滑动窗口,移动时维护窗口内黑色方块或者白色方块的个数。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n,k;
int a[maxn],b[maxn];
string s;
void init(/* arguments */) {
    n=rr();
    qwe(i,0,n-1) a[i]=rr();
    qwe(i,0,n-1) b[i]=rr();
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        n=rr(),k=rr();
        cin>>s;
        int w=0,b=0;
        for(int i=0;i<k;i++){
            if(s[i]=='W') w++;
            else b++;
        }
        int le=0,ri=k-1,ans=INF;
        ans=min(ans,k-b);
        while (ri<n) {
            le++;
            ri++;
            if(ri>=n) break;
            if(s[le-1]=='W') w--;
            else b--;
            if(s[ri]=='W') w++;
            else b++;
            ans=min(ans,k-b);
        }
        std::cout << ans << '\n';
    }
    return 0;
}

C. Restoring the Duration of Tasks

C - Restoring the Duration of Tasks

思路

维护当前的截至时间。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define xx first
#define yy second
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n;
int a[maxn],b[maxn];
void init(/* arguments */) {
    n=rr();
    qwe(i,0,n-1) a[i]=rr();
    qwe(i,0,n-1) b[i]=rr();
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        init();
        int en=0;
        int ans[maxn]={0};
        for(int i=0;i<n;i++) {
            if(a[i]<en) {  // 开始比结束早
                if(b[i]>en) {
                    ans[i]=b[i]-en;
                }
                en=max(en,b[i]);
            }
            if(a[i]>=en) {
                ans[i]=b[i]-a[i];
                en=b[i];
            }
        }
        qwe(i,0,n-1) std::cout << ans[i] << ' ';
        std::cout << '\n';
    }
    return 0;
}

B. Array Decrements

B - Array Decrements

思路

计算出每个id上a-b的值,记录最大值。如果存在ai-bi的值比最大值小,那么bi必须是0.其次不能存在ai<bi的情况。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define xx first
#define yy second
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

int n;
int a[maxn],b[maxn];
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        n=rr();

        qwe(i,0,n-1) a[i]=rr();
        qwe(i,0,n-1) b[i]=rr();
    
        if(n==1) {
            if(a[0]>=b[0]){std::cout << "YES" << '\n';}
            else std::cout << "NO" << '\n';
            continue;
        }
    
        int maxi=-INF,fl=0;
        qwe(i,0,n-1) {
            a[i]-=b[i];
            maxi=max(maxi,a[i]);
            if(a[i]<0) {fl=1;break;}
        }
        if(fl) {
            std::cout << "NO" << '\n';
            continue;
        }
    
        fl=0;
        qwe(i,0,n-1) {
            if(a[i]!=maxi && b[i]) {
                fl=1;
                break;
            }
        }
        if(fl) std::cout << "NO" << '\n';
        else std::cout << "YES" << '\n';
    }
    return 0;

}

A. Print a Pedestal (Codeforces logo?)

A - Print a Pedestal (Codeforces logo?)

思路

设右边x,左边x+1,右边x+2。求出x,根据余数分配给中间和左边值,中间优先级高。

#include <bits/stdc++.h>
typedef long double ld;
typedef long long ll;
#define pb push_back
#define mk make_pair
#define mt make_tuple
#define eb emplace_back
#define pob pop_back
#define rz resize
#define mem(a,b) memset(a,b,sizeof(a))
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define debug(a) cout<<#a<<"="<<a<<endl;
#define xx first
#define yy second
#define qwe(i,a,b) for(int i=a;i<=b;i++)
#define ewq(i,a,b) for(int i=a;i>=b;i--)
inline ll rr(){ll f=1,x=0;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');return f*x;}
using namespace std;
const ll INF=0x3f3f3f3f,inf=0x3f3f3f3f3f3f3f;
const ll mod[2]={int(1e9 + 7), 10007};
const int base[2]={29,31};
const int maxn=2e5+6;
ll qpow(ll x,ll n){ll ans=1;while(n>0){if(n&1)ans=ans*x%mod[1];x=x*x%mod[1];n>>=1;}return ans;}

void init(/* arguments */) {
}
int main(int argc, char const *argv[]) {
    int t=rr();
    while (t--) {
        int d=rr();
        int ans=(d-3)/3;
        int r=d%3;
        int a,b,c;
        b=ans+2+(r>0);
        r--;
        a=ans+1+(r>0);
        r--;
        c=ans;
        std::cout << a<<' '<< b<<' '<<c << '\n';
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值