Day6 下(

T1

模拟,80? 

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
typedef long long LL;
const int N=1e5+100;
int a[N],n,len;
char s[N];
int  w[N],maxn;
LL f[N],tot;
int main()
{
    freopen("maximum.in","r",stdin);
    freopen("maximum.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    cin>>(s+1);
    for(int i=1;i<=n;i++)
    {
        w[i]=s[i]-'0';
        if(w[i])    maxn=i;
    }
    for(int i=1;i<=maxn;i++)
    {
        f[i]=f[i-1];
        if(a[i]>0)    f[i]+=a[i];
    }
    w[0]=1;tot=0;
    while(maxn>=1)
    if(w[maxn])
    {
        if(a[maxn]<=0)
        {
            cout<<(f[maxn-1]+tot)<<endl;
            return 0;
        }
        tot+=a[maxn];
        while(!w[maxn-1]) maxn--;
        maxn--;
    }
    cout<<tot<<endl;
    return 0;
}
first 80 
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
typedef long long LL;
const int N=1e5+100;
int a[N],n,len;
char s[N];
int  w[N],maxn;
LL f[N],tot=0,ans=0;
int main()
{
    freopen("maximum.in","r",stdin);
    freopen("maximum.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    cin>>(s+1);
    for(int i=1;i<=n;i++)
    {
        w[i]=s[i]-'0';
        if(w[i])    maxn=i;
    }
    f[0]=0;
    for(int i=1;i<=maxn;i++)
    {
        f[i]=f[i-1];
        if(a[i]>0)    f[i]+=a[i];
    }
    w[0]=1;tot=0;
    for(int i=maxn;i>=1;i--)
    if(w[i])
    {
    //    printf("%lld %lld\n",i,tot+f[i-1]);
        ans=max(ans,tot+f[i-1]);
        tot+=a[i];
    }
    cout<<ans<<endl;
    return 0;
}
w[0]=1;tot=0;LL all=f[maxn];
    while(maxn>=1)
    {
        if(a[maxn]<=0)
        {
            cout<<(f[maxn-1]+tot)<<endl;
            return 0;
        }
        tot+=a[maxn];
        while(!w[maxn-1]) maxn--;
        maxn--;
    }

调了半天,我终于发现了错误所在。

说实话:我错的真不怨,我感觉很高兴,因为我找到了自己的思维误区

怎么说呢:最大值可能出现在这些情况中的任意一个:

        1除了最高位对应的数外,其他任意位上数的组合。(最高位是0)

        2第二高的为0,其他的任意位上的数的组合。(最高位是1)

        3第三高的为0,其他位上任意数的组合。(前两高的是1)

        ............   这道题中的 最高位 是指 m的二进制位为1的。

做的时候还不如取个max那,我只是想当然的认为:

  当最高位是是负数时,前面的一定比后面的要更优。(这是对的,但是)

  我却认为这时,不加这个最高位的负数的结果是最优的。

其实不然,这时,对于不加这位的结果前面都算过,这一次却不一定是最优的!!!!!!

T2

二分+dp

奇怪的贪心。

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
const int N=1009;
int a[N],b[N];
int n,k;
int L,R,mid,ans;
bool check(int x)
{
    int sum=0,sum0=1e9+1;
    for(int i=1;i<=n;i++)
    a[i]=b[i];
    a[n+1]=a[n];
    for(int i=2;i<=n;i++)
    {
        if(abs(a[i]-a[i-1])>x)
        {
            if(a[i]>a[i-1])
            {
                a[i]=a[i-1]+x;
                sum++;
            }else
            if(a[i-1]>a[i])
            {
                a[i]=a[i-1]-x;
                sum++;
            }
        }        
    }
    int i=1,j=n;
    for(int i=1;i<=n;i++,j--)
        a[i]=b[j];
    a[n+1]=a[n];
    for(int i=2;i<=n;i++)
    {
        if(abs(a[i]-a[i-1])>x)
        {
            if(a[i]>a[i-1])
            {
                a[i]=a[i-1]+x;
                sum0++;
            }else
            if(a[i-1]>a[i])
            {
                a[i]=a[i-1]-x;
                sum0++;
            }
        }        
    }
    sum=min(sum,sum0);
    return sum<=k;
}
int main()
{
    freopen("minimum.in","r",stdin);
    freopen("minimum.out","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);
        R=max(R,b[i]);
    }
    if(k>=n-1)
    {
        cout<<0<<'\n';
        return 0;
    }
    L=0,R;
    while(L<=R)
    {
        mid=(L+R)/2;
        if(check(mid))    R=mid-1,ans=mid;
        else L=mid+1;
    }
    cout<<ans<<'\n';
    return 0;
}
first 30 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n,k;
int a[2000],f[2000];
int L,R,mid;
bool check(int x)
{
    f[1]=0;
    int ans=n;//最大不超过n
    for(int i=2;i<=n;i++)
    {
        f[i]=i;
        for(int j=1;j<i;j++)
        if(abs(a[i]-a[j])<=(1LL*x*(i-j)))
            f[i]=min(f[i],f[j]+(i-j-1));
        ans=min(ans,f[i]+n-i);
    } 
    return ans<=k;
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    L=0,R=1e9+19;
    while(L<R-1)
    {
        mid=(L+R)>>1;
        if(check(mid))    R=mid;
        else L=mid;
    }
    if(check(L))    printf("%d\n",L);
        else printf("%d\n",R);
    return 0;
}
二分+dp判断

 

T3

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
const int N=1e3+10;
char s[N];
int n,x,y,len;
int q,l,r; 
int A[N],B[N];
bool ok[N][N];
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%d%d%d",&n,&x,&y);
    cin>>(s+1);
    for(int i=1;i<=n;i++)
    {
        A[i]=A[i-1];B[i]=B[i-1];
        if(s[i]=='A')    A[i]++;
        else B[i]++;
    }
    for(int i=1;i<=n;i++)
    for(int j=i;j<=n;j++)
    {
        int Asum,Bsum;
        Asum=A[j]-A[i-1];Bsum=B[j]-B[i-1];
        if(1LL*Asum*y==1LL*Bsum*x)    ok[i][j]=1;
    }
    
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&l,&r);
        int L=r-l+1;
        for(L;L>=1;L--)
        for(int i=l;i+L-1<=r;i++)
        if(ok[i][i+L-1])
        {
            printf("%d\n",L);
            L=0,i=r+3;break;
        }
    }
    return 0;
}
first

待续。。。。。。

1用和为0,判断,链表查询,O( n q)。

2分块。

3可持久线段树。。。难写。

最短 函数线段树

 

posted @ 2017-11-02 17:38  浪矢-CL  阅读(129)  评论(0编辑  收藏  举报