线段树
区间修改,区间求和
https://www.luogu.org/problemnew/show/P3372
代码
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=100000+10; ll a[maxn]; ll add[maxn<<2],tree[maxn<<2]; void pushup(int rt){ tree[rt]=tree[rt<<1]+tree[rt<<1|1]; } void build(int l,int r,int rt){ if(l==r){ tree[rt]=a[l]; return ; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } void pushdown(int rt,int ln,int rn){ if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; tree[rt<<1]+=add[rt]*ln; tree[rt<<1|1]+=add[rt]*rn; add[rt]=0; } } void update(int l,int r,int rt,int L,int R,int c){ if(l>=L&&r<=R){ add[rt]+=c; tree[rt]+=c*(r-l+1); return ; } int mid=(l+r)>>1; pushdown(rt,mid-l+1,r-mid); if(L<=mid) update(l,mid,rt<<1,L,R,c); if(R>mid) update(mid+1,r,rt<<1|1,L,R,c); pushup(rt); } ll ask(int l,int r,int rt,int L,int R){ if(l>=L&&r<=R){ return tree[rt]; } int mid=(l+r)>>1; pushdown(rt,mid-l+1,r-mid); ll ans=0; if(L<=mid) ans+=ask(l,mid,rt<<1,L,R); if(R>mid) ans+=ask(mid+1,r,rt<<1|1,L,R); return ans; } int main(){ int n,m; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); int op,x,y,k; while(m--){ scanf("%d",&op); if(op==1){ scanf("%d%d%d",&x,&y,&k); update(1,n,1,x,y,k); } else { scanf("%d%d",&x,&y); printf("%lld\n",ask(1,n,1,x,y)); } } return 0; }
二分
二分,第一个大于x
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1000; int a[maxn]; int main(){ int n; scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } int l=1; int r=n; while(l<=r){ int mid=(l+r)>>1; if(a[mid]>5){若要查找最后一个小于x的改为>=,输出r; r=mid-1; } else l=mid+1; } printf("%d ",l); return 0; }
可以这样理解,查找大于等于的,判断那里就是大于等于,查找小于等于的判断那里是大于
二维前缀和
垃圾炸弹
https://www.lydsy.com/JudgeOnline/problem.php?id=1218
代码
#include<cstdio> #include<algorithm> using namespace std; const int maxn=5050; int sum[maxn][maxn]; int main(){ int n,r; int x,y,w; scanf("%d%d",&n,&r); for (int i=1;i<=n;i++){ scanf("%d%d%d",&x,&y,&w); sum[x+1][y+1]=w; } for (int i=1;i<=5001;i++) sum[1][i]=sum[1][i-1]+sum[1][i]; for (int i=1;i<=5001;i++) sum[i][1]=sum[i-1][1]+sum[i][1]; for (int i=2;i<=5001;i++){ for (int j=2;j<=5001;j++){ sum[i][j]=sum[i-1][j]+sum[i][j-1]+sum[i][j]-sum[i-1][j-1]; } } int ans=0; for (int i=r;i<=5001;i++){ for (int j=r;j<=5001;j++){ ans=max(ans,sum[i][j]-sum[i-r][j]-sum[i][j-r]+sum[i-r][j-r]); } } printf("%d",ans); return 0; }
前缀和
https://www.luogu.org/recordnew/show/11207133
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int maxn=100000+10; ll sum[maxn]; int main(){ int n,k,y; scanf("%d%d",&n,&k); for (int i=1;i<=n;i++){ scanf("%d",&y); sum[i]=sum[i-1]+y; } ll ans=0; for (int i=k;i<=n;i++) ans+=(sum[i]-sum[i-k]); printf("%lld",ans); return 0; }
快速幂
https://www.luogu.org/problemnew/show/P1226
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; ll mod; ll quickmod(ll a,ll b,ll mod){ ll ans=1%mod; for (;b;b>>=1){ if(b&1) ans=ans*a%mod; a=a*a%mod; } return ans%mod; } int main(){ ll a,b; scanf("%lld%lld%lld",&a,&b,&mod); printf("%lld^%lld mod %lld=%lld",a,b,mod,quickmod(a,b,mod)); return 0;
}