P8218 【深进1.例1】求区间和
思路:
模板题
代码:
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N];
int s[N];
int main()
{
int n,m;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
cin>>m;
while (m--)
{
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
P1719 最大加权矩形
思路:
保存数值之后,求前缀和,之后求用两个指针模拟每个点,求每个点到两个指针的区间和,比大小即可
代码:
时间复杂度o(n^4)
#include <iostream>
using namespace std;
const int N=130;
int map[N][N];
int s[N][N];
int ans;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>map[i][j];
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+map[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
for(int q=i;q<=n;q++)
for(int p=j;p<=n;p++)
{
int temp=s[q][p]-s[i-1][p]-s[q][j-1]+s[i-1][j-1];
ans=max(ans,temp);
}
}
cout<<ans<<endl;
return 0;
}
P1314 [NOIP2011 提高组] 聪明的质监员
思路:
因为,W的值越大,所选择的范围越小,所以Y越小,W值越小,所选择的范围越大,所以Y越大,所以我们就会得到一个关系W和Y之间的一个关系,因为要求|s-y|的最小值,所以根据Y与s的值,确定W。
所以,根据这个关系,以w的最大值+1与w的最小值为范围(因为,当W为最小的时候,所有石头都可以选,Y最大,当W为最大的时候,应该是所有石头都不能选,此时Y最小,所以我们要保证能二分出来,W的最小和W的最大,也就是w最大值+1),二分出来一个W, 之后用这个W在计算|s-y|的值
需要注意的是,因为我们求的值是绝对值,所以二分的方法,就会特别讲究,如果不存在y==s的值的话,两个模板二分出来的就会是大于最合适的W的第一个值,或小于最合适W的第一个值,这是就需要比较那个距离W的位置近,但这样的话就会TLE,所以我们最好的解决方法就是一个模板在查找的过程中比较,最后输出比较出来的值就行。
以下是两种模板分别二分出来的结果:
从右向左找
从左向右找
AC代码:
时间复杂度o(n)
#include <iostream>
using namespace std;
const int N=1e6+10;
int w[N],v[N];
long long sw[N],sv[N];
long long ans=0x3f3f3f3f3f3f3f3f;
long long sum=0x3f3f3f3f3f3f3f3f;
int maxw,minw=0x3f3f3f3f;
int l1[N],r1[N];
int n,m;
long long s;
long long check(long long W)
{
for(int i=1;i<=n;i++)
{
if(w[i]>=W)
{
sw[i]=sw[i-1]+1;
sv[i]=sv[i-1]+v[i];
}
else
{
sw[i]=sw[i-1];
sv[i]=sv[i-1];
}
}
long long y=0;
for(int i=0;i<m;i++)
{
int l=l1[i],r=r1[i];
y+=(sw[r]-sw[l-1])*(sv[r]-sv[l-1]);
}
sum=llabs(s-y);
return y;
}
int main()
{
scanf("%d%d%lld",&n,&m,&s);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&w[i],&v[i]);
maxw=max(maxw,w[i]);
minw=min(minw,w[i]);
}
maxw++;
for(int i=0;i<m;i++)
{
scanf("%d %d",&l1[i],&r1[i]);
}
long long l=minw,r=maxw;
while (l<r)
{
long long mid=l+r+1>>1;
if(check(mid)>=s)l=mid;
else r=mid-1;
if(sum<ans) ans=sum;
}
cout<<ans<<endl;
return 0;
}