一、差分
1.洛谷P1083借教室 (NOIP2012) https://www.luogu.com.cn/problem/P1083
比较显然的一种做法 : 求哪一天显然具有单调性,可以二分。那么每一次check的时候差分,总复杂度 O( n* log m )级别
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 4; int n,m; ll r[maxn],s[maxn],t[maxn],d[maxn],tmp[maxn]; bool check(int x) { for(int i=1;i<=n;i++) tmp[i]=0; for(int i=1;i<=x;i++) { tmp[s[i]]-=d[i]; tmp[t[i]+1]+=d[i]; } for(int i=1;i<=n;i++) { tmp[i]+=tmp[i-1]; if(tmp[i]+r[i]<0) return true; } return false; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&r[i]); for(int i=1;i<=m;i++) scanf("%lld%lld%lld",&d[i],&s[i],&t[i]); int l=1,r=m,mid,ans=m+1; while(l<=r) { mid=(l+r)>>1; if(check(mid)) r=mid-1,ans=min(ans,mid); else l=mid+1; } if(ans!=m+1) printf("-1\n%d",ans); else printf("0"); return 0; }学了一种做法 :O( n + m ) 的优秀复杂度 。 先做完差分,然后检查是否都符合要求,如果不符合,从后往前撤回订单,直到符合的位置即为答案。
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 4; ll r[maxn],s[maxn],t[maxn],d[maxn],f[maxn]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&r[i]); for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&d[i],&s[i],&t[i]); f[s[i]]+=d[i]; f[t[i]+1]-=d[i]; } int now=m,ans=m+1; ll sum=0; for(int i=1;i<=n;i++) { sum+=f[i]; if(sum>r[i]) { while(sum>r[i]) { f[s[now]]-=d[now]; f[t[now]+1]+=d[now]; if(s[now]<=i&&t[now]>=i) sum-=d[now]; now--; } ans=now+1; } } if(ans==m+1) printf("0"); else printf("-1\n%d",ans); return 0; }
二、单调栈
1.一个被坑过的题,比较典型的单调栈 https://blog.nowcoder.net/n/94a66c4dd8b249cab23928ceecc0da8c
2.2019牛客多校第八场 A
题干 :
链接:https://ac.nowcoder.com/acm/contest/888/A 来源:牛客网 Gromah and LZR entered the great tomb, the first thing they see is a matrix of size n×m , and the elements in the matrix are all 0 or 1. LZR finds a note board saying "An all-one matrix is defined as the matrix whose elements are all 1, you should determine the number of all-one submatrices of the given matrix that are not completely included by any other all-one submatrices". Meanwhile, Gromah also finds a password lock, obviously the password should be the number mentioned in the note board! Please help them determine the password and enter the next level.分析 :
三、单调队列
1.经典题目——滑动窗口 https://www.luogu.com.cn/problem/P1886
分析 :head和tail动动动,滑滑滑
code :
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 5; int a[maxn]; struct Node { int v,id; }q[maxn],Q[maxn]; //其实只要一个就行了 int main() { int n,k,head=1,tail=1; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); Q[1].v=q[1].v=a[1]; Q[1].id=q[1].id=1; for(int i=1;i<=n;i++) { while(head<=tail&&i-q[head].id>=k) head++; while(head<=tail&&q[tail].v>=a[i]) tail--; q[++tail].v=a[i]; q[tail].id=i; if(i>=k) printf("%d ",q[head].v); } printf("\n"); tail=1,head=1; for(int i=1;i<=n;i++) { while(head<=tail&&i-Q[head].id>=k) head++; while(head<=tail&&Q[tail].v<=a[i]) tail--; Q[++tail].v=a[i]; Q[tail].id=i; if(i>=k) printf("%d ",Q[head].v); } return 0; }