臭道人

1.25

https://ac.nowcoder.com/acm/problem/207040

感悟:①尺取法,两个指针的行进方向是固定的,不会中途变向.

收获:①对于圆形问题的尺取法操作(取模操作).

②圆形问题的性质,就是处理周长一半的情况

#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N],s[N],sum,i,j,res,now;
int main()
{
    int n;cin>>n;
    for(int i=0;i<n;i++)
    scanf("%d",&a[i]),sum+=a[i];
    int r=0,l=0;
    while(l<n)
    {
        while(now<sum/2)
        {
            now+=a[(r++)%n];//当r绕了一圈进行第二圈及以上时 
        }
        res=max(res,min(now,sum-now));//如果超过sum的一半,需要记录小的那个 
        now-=a[l];
        l++;
    }
    cout<<res;
}

 

 

https://ac.nowcoder.com/acm/problem/18386

尺取法真好用

自己的不足:①前几次尝试的时候陷入一个未知错误,一直跑不出结果(就是没有输出),也不是死循环

②不确定min更新放在哪个地方.

#include<iostream>
using namespace std;
int a[100];
int judge()
{    int i;
    for(i=0;i<=25;i++)
    if(!a[i])return 0;
    return 1;
}
int main()
{
    string ch;
    cin>>ch;
    int len=ch.length();
    int r=0,l=0,ans=1e6;
    while(r<len)
    {
        a[ ch[r]-'a'  ]++;
        while( judge() )
        {
            ans=min(ans,r-l+1); 
            a[ch[l]-'a']--;
            l++;
        }
        r++;
    }
    cout<<ans;
    
}

 

https://ac.nowcoder.com/acm/problem/107658

解法①,和1.24一样,双指针,感觉性能不行:

然后,自己的逻辑链还没完全理清楚,这种题目还没有形成套路,码的时候耽误了挺久,不能立刻码出来

多练习几遍,和1.24的题

#include<iostream>
using namespace std;
const int N=1e5+10;
const int Min=1e8+1;
int a[N];
int read()
{
    int x=0,f=0;char ch=getchar();
    while(ch<48||ch>57)f|=ch=='-',ch=getchar();
    while(ch>=48&&ch<=57)x=x*10+ch-48,ch=getchar();
    return f?-x:x;
}
int main()
{
    int t=read();
    while(t--)
    {
        int n=read(),s=read(),ans=Min,sum=0,l=1,r=1;
        while(r<=n)
        {
            a[r]=read();
            sum+=a[r];
            if(sum>=s)
                {            
                    ans=min(ans,r-l+1);
                    while(sum>=s)
                        sum-=a[l++];
                    ans=min(ans,r-l+2);
                }
            r++;
        }
        if(ans==Min)cout<<0<<endl;
        else cout<<ans<<endl;
    }
} 

 前缀和解法:

#include<iostream>
using namespace std;
inline int read()
{
     int x=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
inline void write(int x)
{
    if(x>10)
        write(x/10);
    putchar(x%10+48);
}
#define ll long long
ll sum[100010];
int main()
{
    int t=read();
    while(t--)
    {
        int n=read(),s=read();
        for(int i=1;i<=n;i++)
            {
                int x=read();
                sum[i]=sum[i-1]+x;
            }
        int i=1,j,ans=n+1;
        for(j=1;j<=n;j++)
            {
                if(sum[j]-sum[i]<s)continue;
                while(sum[j]-sum[i]>=s)i++;
                ans=min(ans,j-i+1);
            }
            ans= (ans==n+1?0:ans);
        write(ans),putchar('\n');
    }
    
}

另外发现一个很神秘的事情,用不同的编译器提交的效果完全不一样

用g++提交的时候,内存占用变大了,但是性能提高了125倍多

 

https://www.acwing.com/solution/content/3472/

单链表

#include<iostream>
using namespace std;
const int N=1e6+10;
//      e[N]中存value,ne[N]存下一个结点的下标 
int head,e[N],ne[N],idx,a;
void init()//初始化
{
    head=-1,idx=0;
 } 
 void insert(int a)//头插 
 {    //帮助理解,head是一个指针,指向头节点的下一个节点; 
     e[idx]=a,ne[idx]=head,head=idx++;
 }  //插在下标为k的后面.          
 void add(int k,int x)
 {
     e[idx]=x,ne[idx]=ne[k],ne[k]=idx++;
 }
 void remove(int k) {
     ne[k]=ne[ne[k]];
 }
int main()
{
    init();
    cin>>a;
    while(a--)
    {
        string op;
        int k,x;
        cin>>op;
        if(op=="D")
        {

            cin>>k;
            if(!k)head=ne[head];
            remove(k-1);
        }
        else if(op=="H")
        {
            cin>>x;
            insert(x);
        }
        else if(op=="I"){
            int k,x;
            cin>>k>>x;
            add(k-1,x);
        }
    }
    for(int i=head;i!=-1;i=ne[i])
      cout<<e[i]<<" ";
    return 0;

}

 数学考试

https://ac.nowcoder.com/acm/problem/15553

①前缀和的题目.

原来寻找左区间和右区间的最大值原来可以同时完成,不禁感叹思维的高妙.

核心代码:

l = max(l , s[i]-s[i-k]);
r = max(r , l+s[i+k]-s[i]);

②习惯问题,有一个节点查了很久,后来发现是  最初的max值没开成最小,

养成习惯:把最初的max开成负无穷,把最初的min开成正无穷.

整体代码:

#include<iostream>
#define ll long long 
using namespace std;
const long long int N=3e7;
const long long Max=1e18;
long long a[N],s[N];
long long read()
{
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}
int main()
{    
    int t;cin>>t;
    while(t--)
    {    int i,j;
        long long l=-Max,r=-Max;
        int n,k;cin>>n>>k;
        for(i=1;i<=n;i++)
            a[i]=read(),s[i]=s[i-1]+a[i];
        for(i=k;i+k<=n;i++)//左值和右值相关,并不是割裂的
        {
            l=max(l,s[i]-s[i-k]);
            r=max(r,l+s[i+k]-s[i]);
        }
        cout<<(r)<<endl;    
    }
}

 

posted on 2021-01-25 00:27  臭总  阅读(224)  评论(0编辑  收藏  举报

导航