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; } }