Codeforces Round #424Div. 2题解

来源:互联网 发布:包装效果图制作软件 编辑:程序博客网 时间:2024/06/05 20:40

A题水题:判断是否只有一个波峰并且满足波峰左侧递增右侧递减

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>using namespace std;int n;int a[1000];int main(){    int d = 1;    scanf("%d",&n);    for(int i = 0; i < n; i++)        scanf("%d",&a[i]);    int ok = 1;    for(int i = 1; i < n; i++){        if(d == 0&&a[i]>a[i-1]){            ok = 0;            break;        }        if(d == -1&&a[i]>=a[i-1]){            ok = 0;            break;        }        if(a[i] == a[i-1])            d = 0;        else if(a[i] < a[i-1])            d = -1;    }    ok?puts("YES"):puts("NO");    return 0; }

B:字符串转化一下就可以了

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char s1[30];char s2[30];int mp[256];char str[1005];int main(){    scanf("%s%s",s1,s2);    int len = strlen(s1);    for(int i = 0; i < len; i++)        mp[s1[i]] = i;    scanf("%s",str);    len = strlen(str);    for(int i = 0; i < len; i++){        if(str[i]>='A'&&str[i]<='Z')            printf("%c",toupper(s2[mp[tolower(str[i])]]));        else if(str[i]>='a'&&str[i]<='z')            printf("%c",s2[mp[str[i]]]);        else            printf("%c",str[i]);    }    printf("\n");    return 0; } 

C:你就是拿最小的分数拿去求原始的分数然后求其他分数能不能满足,记得去重

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<set>using namespace std;const int mx = 40005;int a[mx],f[mx],b[mx];set<int>st,ans;int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF){        for(int i = 0; i < n; i++)            scanf("%d",&a[i]);        f[0] = a[0];        st.clear();        for(int i = 1; i < n; i++)            f[i] = f[i-1]+a[i];        for(int i = 0; i < n; i++)            st.insert(f[i]);            for(int i = 0; i < m; i++)            scanf("%d",&b[i]);        sort(b,b+m);        ans.clear();        for(int i = 0; i < n; i++){            int sum = b[0]-f[i];            int ok = 1;            for(int j = 1; j < m; j++){                int s = b[j]-sum;                if(st.find(s)==st.end()){                    ok = 0;                    break;                 }            }            if(ok)                ans.insert(sum);        }        printf("%d\n",ans.size());    }    return 0;}

D:将他们按坐标排序好后他们满足单调性此时可以用二分求解

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long int ll;const int mx = 2005;ll g[mx][mx];int a[mx],b[mx];int n,m;int p;bool check(ll x){    int t = 0;    for(int i = 0; i < m; i++){        if(g[t][i]<=x)            t++;        if(t>=n)            return true;    }    return false;}int main(){    cin>>n>>m>>p;    for(int i = 0; i < n; i++)        cin>>a[i];    for(int i = 0; i < m; i++)        cin>>b[i];    sort(a,a+n); //要排序才能使得决策具有单调性     sort(b,b+m);    for(int i = 0; i < n; i++)        for(int j = 0; j < m; j++)                g[i][j] = abs(a[i]-b[j])+abs(b[j]-p);    ll l = 0,r = 2e9+1;    while(l<r){        ll mid = (l+r)/2;        if(check(mid))            r = mid;        else            l = mid+1;    }    cout<<r<<endl;    return 0;} 

E:用树状数组维护一下中间被删除了几个位置然后,求他们的第下一个比他大的牌在距离是多少再减去被删除的个数就是答案

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<set>using namespace std;typedef long long int ll;const int mx = 2e5+5;int n;int a[mx];set<int>st[mx];int sum[mx];void add(int x){    while(x<=n){        sum[x]++;        x += x&(-x);     }}int sums(int x){    int ans = 0;    while(x){        ans += sum[x];        x -= x&(-x);    }    return ans;}int main(){    scanf("%d",&n);    for(int i = 1; i <= n; i++){        scanf("%d",&a[i]);        st[a[i]].insert(i);    }    sort(a+1,a+n+1);    int pre  = 0;    ll ans = 0;    for(int i = 1; i <= n; i++){        auto it = st[a[i]].lower_bound(pre);        if(it == st[a[i]].end()){            it = st[a[i]].begin();            ans += *it+n-pre;            ans -= sums(n)-sums(pre)+sums(*it);            pre = *it;            add(*it);            st[a[i]].erase(*it);        }        else{            ans += *it-pre;            ans -= sums(*it)-sums(pre);            pre = *it;            add(*it);            st[a[i]].erase(*it) ;        }       }    cout<<ans<<endl;    return 0;}

F:假设天数是x那么

n1x+n2x+….+nnx-a1-a2-…-an<=k

x <= k+a1+a2+…an/(n1+n2+…nn)

因为n和x都是整数那么只要循环sqrt(k+a1+a2..+an)枚举每一个x和k+a1+a2+…an/(n1+n2+…nn)是否满足即可,如果超过了根号那么之前的就会重复没有任何意义。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;typedef long long int ll;ll n,k;ll a[105];bool check(ll x){    ll ans = 0;    for(int i = 1; i <= n; i++)        ans += ((a[i]-1)/x+1)*x-a[i];    return ans<=k;  }int main(){    cin>>n>>k;    ll sum = k;    ll ans = 0;    for(int i =1; i <= n; i++){        cin>>a[i];        sum += a[i];    }    for(ll i = 1; i*i<=sum;i++){        if(check(i))            ans = max(ans,i);        if(check(sum/i))            ans = max(ans,sum/i);    }    cout<<ans<<endl;    return 0;}