湖南集训day2

难度:☆☆

 

 

/*显然可以前缀和*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 100007

using namespace std;
int n,m,ans,cnt;
int a[N],sum[N];char s[N];

int main()
{
    freopen("reverse.in","r",stdin);
    freopen("reverse.out","w",stdout);
    scanf("%s",s);n=strlen(s);ans=N+N;
    if(n==1) 
    {
        printf("0\n");
        return 0;
    }
    for(int i=0;i<n;i++) a[i+1]=s[i]=='0'?0:1;
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
    for(int i=0;i<=n;i++)
    {
        ans=min(ans,sum[i]+n-i-(sum[n]-sum[i]));
    }
    printf("%d\n",ans);
    return 0;
}

 

 

/*
枚举,用vis一个二进制数组表示当前数每一位的状态,出现或者不出现。 
然后把二进制转为十进制,cnt[十进制]+1。
最后因为要求多少对,所以答案累加C(i,2)。 
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define size 1024

using namespace std;
int n,cnt[size],vis[10];
int Use[10]={1,2,4,8,16,32,64,128,256,512};
long long ans;

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    cin>>n;
    int start,End;
    for(int i=1;i<=n;i++)
    {
        start=i;End=0;memset(vis,0,sizeof vis);
        while(start) vis[start%10]=1,start/=10;
        for(int j=0;j<=9;j++) if(vis[j]) End+=Use[j];
        cnt[End]++;
    }
    for(int i=0;i<size;i++) ans+=1ll*cnt[i]*(cnt[i]-1)/2;
    cout<<ans<<endl;
    fclose(stdin);fclose(stdout);
    return 0;
}

 

/*
做法类似最长上升子序列
线段树可以优化到70,不会写没治...
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>

#define N 10000007

using namespace std;
int dp[N],a[N],cnt[N];
int n,k,ans;

int main()
{
    freopen("wave14.in","r",stdin);
    freopen("wave.out","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) dp[i]=cnt[i]=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            if(abs(a[j]-a[i])>=k) 
            {
                if(cnt[j]%2==0 && a[i]<a[j])
                {
                     if(dp[i]<dp[j]+1) dp[i]=dp[j]+1,cnt[i]=cnt[j]+1;
                }
                else if(cnt[j]%2!=0 && a[i]>=a[j]) 
                {
                     if(dp[i]<dp[j]+1) dp[i]=dp[j]+1,cnt[i]=cnt[j]+1;
                }
                else dp[i]=max(dp[i],dp[j]);
            }
        }
    }  
    printf("%d\n",dp[n]);
    fclose(stdin);fclose(stdout);
    return 0;
}
30分暴力dp
/*
很神奇。
贪心,在满足k的限制下,偶数项尽量大,奇数项尽量小。
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 2000007

using namespace std;
int a[N];
int n,k,m,ans,cur;

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int main()
{
    n=read();k=read();
    for(int i=0;i<n;i++) a[i]=read();
    ans=1,m=0,cur=a[0];
    for(int i=1;i<n;i++)
    {
        if(m)
          if(cur-a[i]>=k)
            m=0,ans++,cur=a[i];
          else cur=max(cur,a[i]);
          
        else
          if(a[i]-cur>=k)
            m=1,ans++,cur=a[i];
          else cur=min(cur,a[i]);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-10-09 17:54  安月冷  阅读(245)  评论(0编辑  收藏  举报