[Codeforces #211] Tutorial

Link:

Codeforces #211 传送门

一套非常简单的题目,但很多细节都是错了一次才能发现啊……

还是不能养成OJ依赖症,交之前先多想想corner case!!!

 

A:

模拟,要特判0啊

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
int n;
void solve(int x)
{
    if(x<5) printf("O-|");
    else printf("-O|");
    if(x>=5) x-=5;
    for(int i=1;i<=x;i++) printf("O");
    printf("-");
    for(int i=1;i<=4-x;i++) printf("O");
    puts("");
}

int main()
{
    scanf("%d",&n);
    if(!n) solve(0);//特判0! 
    while(n) solve(n%10),n/=10;
    return 0;
}
Problem A

 

B:

模拟,范围是$1.5*1e5$!!!仔细读题啊

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
int n,k,cur,dat[150005];P res;
//范围是1.5*1e5!
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
    for(int i=1;i<=k;i++) cur+=dat[i];
    res.X=1;res.Y=cur;
    for(int i=1;i<=n-k;i++)
    {
        cur-=dat[i];cur+=dat[i+k];
        if(res.Y>cur) res.Y=cur,res.X=i+1;
    }
    printf("%d",res.X);
    return 0;
}
Problem B

 

C:

string.erase和vector.erase一样,尽量不要用

期望复杂度是$O(n)$级别的

此题为了支持删除我还手写了个链表……

其实不用两次扫描+删除+输出,只要扫一遍,边扫边判断当前字母能否加入答案就行了

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
const int MAXN=2e5+10;
char s[MAXN];int len,k,nxt[MAXN];

int main()
{
    scanf("%s",s+1);len=strlen(s+1);
    for(int i=1;i<=len;i++) nxt[i]=i+1;
    k=1;nxt[len+1]=len+1;
    while(nxt[nxt[k]]!=len+1)
        if(s[k]==s[nxt[k]]&&s[nxt[k]]==s[nxt[nxt[k]]])
            nxt[k]=nxt[nxt[k]];
        else k=nxt[k];
    k=1;
    while(nxt[nxt[nxt[k]]]!=len+1)
        if(s[k]==s[nxt[k]]&&s[nxt[nxt[k]]]==s[nxt[nxt[nxt[k]]]])
            nxt[nxt[k]]=nxt[nxt[nxt[k]]];
        else k=nxt[k];
    k=1;
    while(k!=len+1) printf("%c",s[k]),k=nxt[k];
    return 0;
}
Problem C

 

D:

答案的可行性具有单调性,明显可以二分

由于使用自己的钱数为$a-\sum p_i$,和哪些人参与购买无关

因此每次判断时可以采取贪心的策略

1、选择拥有钱数最多的$k$个人和价格最低的$k$个车购买

2、为了使额外挪用的钱数不超过$a$,人和车从小到大排序后一一对应明显是最优的选择

 

最后要特判$\sum p_i\le a$的情况,此时直接减会出现负数,因此要用最终答案和0取max!!!

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef long long ll;
typedef double db;
typedef pair<int,int> P;
const int MAXN=1e5+10;
int n,m,a,p[MAXN],b[MAXN];ll pre[MAXN];

bool check(int x)
{
    ll sum=0;
    for(int i=1;i<=x;i++)
        if(b[n-x+i]<p[i]) sum+=p[i]-b[n-x+i];
    return sum<=a;
}

int main()
{
    scanf("%d%d%d",&n,&m,&a);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=m;i++) scanf("%d",&p[i]);
    sort(b+1,b+n+1);sort(p+1,p+m+1);
    for(int i=1;i<=m;i++) pre[i]=pre[i-1]+p[i];
    
    int l=0,r=min(m,n);
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid)) l=mid+1;
        else r=mid-1;
    }//答案一定要记得取MAX! 
    printf("%d %d",r,max(pre[r]-a,0ll));
    return 0;
}
Problem D

 

E:

貌似题解出锅了……

后面再填吧,其实就是一个预处理+暴力枚举

 

posted @ 2018-08-19 19:02  NewErA  阅读(151)  评论(0编辑  收藏  举报