前缀和很好理解,其实也就是为了后期方便计算
#include<iostream>
using namespace std;
const int N=100010;
int n,m;
int a[N],s[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+a[i];
}
while(m--)
{
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1];
}
return 0;
}
一维的很好理解
#include<iostream>
using namespace std;
const int N=1010;
int n,m,q;
int s[N][N];
int main()
{
cin<<n<<m<<q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin<<s[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
while(q--)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
cout<<s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
}
}
P1115
最大子段和:
这个把每个段的和求出来,然后循环着去减,应该可以解决的,但我猜必定超时
好一点的办法:
用一点点dp的思想:就是说每次新加入进来一个,那么对于这样一个长度的段,它的最大子列长度是:原有的(>0)+他自己 他自己
当他选择后者的时候,前面的就戛然而止了,所以需要ans存每一次的最大值,防止丢掉,其实也就是是sum>0,再继续加
#include<iostream>
#include<math.h>
using namespace std;
long long int h,maxn[2000001],a[2000001],ans=-99999999;
int main()
{
cin>>h;
for(int i=1;i<=h;i++)
{
cin>>a[i];
maxn[i]=max(a[i],maxn[i-1]+a[i]);
ans=max(ans,maxn[i]);
}
cout<<ans;
return 0;
}
P3397
这个题目就是非常明显的的用二维前缀来做,一开始这个矩形全部都是0,然后接下去就直接循环+1
没意思
#include<iostream>
using namespace std;
int main()
{
int n,m,a[1100][1100]={0},x1,x2,y1,y2;
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>x1>>y1>>x2>>y2;
for(int i=x1-1;i<=x2-1;i++)
{
for(int j=y1-1;j<=y2-1;j++)
{
a[i][j]++;
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
P1719
求最大加权矩阵,先把每个以自己为右下角大的矩形里面的值给算出来,用循环算,然后或许可以循环两遍,把每一种的都算出来,四重循环
具体一点来说
p,k要放在是较大的的那两个,其他的是上面的,然后每一次更新最大值
#include<iostream>
using namespace std;
int m,sum[130][130]={0},a[130][130],maxn=-109,hh;
int main()
{
cin>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
sum[1][1]=a[1][1];
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=i;k<=m;k++)
{
for(int p=j;p<=m;p++)
{
hh=sum[k][p]-sum[k][j-1]-sum[i-1][p]+sum[i-1][j-1];
maxn=max(maxn,hh);
}
}
}
}
cout<<maxn;
}
P2880
千呼万唤使出来的ST表
#include<bits/stdc++.h>
using namespace std;
int lxy[180010][22],hrb[180010][21],n,m,i,j,k,l,r;
int ST(int l,int r)
{
int s=log2(r-l+1),x,y;
x=max(lxy[l][s],lxy[r-(1<<s)+1][s]);
y=min(hrb[l][s],hrb[r-(1<<s)+1][s]);
return x-y;}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&lxy[i][0]),hrb[i][0]=lxy[i][0];
for(i=1;i<=21;i++)
for(k=1;k+(1<<i)<=n+1;k++)
{
lxy[k][i]=max(lxy[k][i-1],lxy[k+(1<<(i-1))][i-1]);
hrb[k][i]=min(hrb[k][i-1],hrb[k+(1<<(i-1))][i-1]);
}
for(i=1;i<=m;i++) {
scanf("%d%d",&l,&r);
printf("%d\n",ST(l,r));
}
return 0;//结束
}
s指的是x,y之间距离可以取得2的多少次
根据你的预处理:就是两次从小到大的循环,外循环是2的多少次,最多不过21,内循环是确保他不超的,可以得到其从i个元素开始长度位为2^j个元素的最值
RMQ(Li,Ri)=max(f[Li][x],f[Ri-2^x+1][x])