Codeforces Round #227 (Div. 2)

u010660276發表於2014-02-03

A. George and Sleep

題意:給你終止時刻和經歷時間,問起始時刻。

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    //freopen("in.txt","r",stdin);
    int s1,s2,t1,t2,ans1,ans2;
    scanf("%d:%d",&s1,&s2);
    scanf("%d:%d",&t1,&t2);
    if(s2<t2)s2+=60,s1-=1;
    if(s1<t1)s1+=24;
    ans2=s2-t2;
    ans1=s1-t1;
    printf("%02d:%02d\n",ans1,ans2);
    return 0;
}

B. George and Round

題意:已經有m道題,一共需要n道題,每道題都有複雜度,大複雜度可以降低為小複雜度,問至少還要重新編多少道題才能滿足要求。

思路:從後往前遍歷,只要>=就能滿足要求。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=3030;
int n,m;
int a[maxn],b[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++)cin>>b[i];
    int ans=n;
    int i=n,j=m;
    while(i>=1&&j>=1)
    {
        if(a[i]<=b[j]){ans--;i--;j--;}
        else if(a[i]>b[j])i--;
    }
    cout<<ans<<endl;
    return 0;
}

C. George and Number

貪心,如果比較的l==r-1就直接比較前面一長段和這一段。l!=r-1就比較l是否大於r-1即可。

#include <iostream>
#include <string>
using namespace std;
string s;
bool concat(int l,int r)
{
    if(l!=r-l)
        return l>r-l;
    else
        return s.substr(0,l)>=s.substr(l,r-l);
}
int main()
{
    while(cin>>s)
    {
        int l = s.length()-1;
        int r = s.length();
        int ans = 0;
        while(l>=0)
        {
            if(s[l]!='0')
            {
                if(concat(l,r))
                {
                    r = l;
                    ans++;
                }
            }
            l--;
        }
        cout<<ans+1<<endl;
    }
    return 0;
}

E. George and Cards

題目大意:給出一個長度為n的序列,然後在給出一個長度為k的條件序列,要求將原先的刪除n-k個後得到的序列滿足條件序列,條件序列b[i],表示序列的前i個元素中必須包含有b[i]這個數。刪除操作,選取一個區間,刪除中間的最小值,並且獲得相應的區間長度的獎勵,問說最多可以獲得多少獎勵


解題思路:二分+樹狀陣列。首先,可以分析的出結論,b陣列即為原先陣列刪除n-k個後的目標陣列(想一下就知道的b[1]的位置肯定是放值為b[1]的卡片,那麼值為b[2]的卡片就只能放在2上,以次類推);其次,為了得到儘量多的獎勵,在刪除元素時選取的區間就要儘量長,不僅如此,在刪除元素時也要從小的開始刪除,因為刪除大的會導致刪除小的時候區間長度的縮短;這樣的話就可以通過將序列每個數按照從小到大的順序將位置放入set中,碰到需要刪除的元素就去二分上下限。知道上下限就可以通過BIT求得中間存在元素的個數。

#include<iostream>
#include<set>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1000005;
typedef long long LL;
int p[maxn],b[maxn],tree[maxn];
int n,k,a;
void add(int x,int v)
{
    while(x<=n)
    {
        tree[x]+=v;
        x+=x&(-x);
    }
}
LL sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=tree[x];
        x-=x&(-x);
    }
    return ans;
}
void solve()
{
    set<int> s;
    set<int>::iterator iter;
    LL ans=0;
    s.insert(0),s.insert(n+1);
    for(int i=1;i<=n;i++)
    {
        if(b[i])
        {
            s.insert(p[i]);
            continue;
        }
        iter=s.upper_bound(p[i]);
        int r=*iter-1;
        int l=*(--iter);
        ans+=sum(r)-sum(l);
        add(p[i],-1);
    }
    cout<<ans<<endl;
}
int main()
{
    //freopen("in.txt","r",stdin);
    cin>>n>>k;
    memset(tree,0,sizeof(tree));
    memset(b,0,sizeof(b));
    memset(p,0,sizeof(p));
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        p[a]=i;
        add(i,1);
    }
    for(int i=1;i<=k;i++)
    {
        cin>>a;
        b[a]=1;
    }
    solve();
    return 0;
}


相關文章