本周总结:

1.scanf,printf,输入输出,该输入输出方式来源于c,而c++兼容c,并且scanf,printf的运行时间相比cin,cout来说快很多,所以在写程序的时候经常使用scanf,printf
.
2.时间复杂度:算法复杂度就是大致估算程序大致运行的时间,将每一个执行语句看做一个单元,找出其余程序的数学关系,忽略系数与常数,常见复杂度从小到大排序如下:
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)

3.二分:

减少循环的次数,将时间复杂度降为O(logn),二分的大致思路就是先根据题目写出一个判断函数,再根据一个值是否符合该函数条件,从而将之后的循环区间缩为[l,r-1]或[l+1,r],达到减少运行时间的目的.用两个大致模板和一道例题来具体说明:

(1):左边界:

while(l<r)
{
  int mid = (l+r)/2;
  if(check(mid)) r=mid;//如果符合check()条件(即题目要求)缩小边界为[l,mid]
  else l=mid+1;//如果不符合check()条件缩小边界为[mid+1,r]
}

(2)右边界:

while(l<r)
{
    int mid = (l+r+1)>>1;
    if(a[mid]<=num) l = mid;//使用a[mid]还是check()看题目要求定
    else r = mid-1;
}

l+r+1是为了避免出现l与r相邻时出现死循环

蓝桥1323题例:

#include<bits/stdc++.h>
using namespace std;
const int max1 = 1e5+5;
int x[max1];
int y[max1];
int k,n;
int check(int num)//根据题目要求先写check()函数
{
	int sum=0;
	for(int i=0;i<n;i++)
	{
		sum+=(x[i]/num*y[i]/num);在边长为num情况下能切巧克力块数总和
	}
	if(sum>=k)
	return 1;
	else
	return 0;
}
int main()
{
	int en=0;
	scanf("%d %d",&n,&k);//输入巧克力数,人数
	for(int i=0;i<n;i++)
	{
		scanf("%d %d",&x[i],&y[i]);//每块巧克力的边长
	}
	int l=1,r=max1;
	while(l<=r)
	{
		int mid = (r+l)/2;
		if(check(mid))     //如果check()符合,则继续增大边长num
		{
		 en = mid;        //定义一个全局变量接受num最大值
		 l = mid+1;
	    }
		else             //如果check()不符合,即不够一人一块,缩小num
		r=mid-1;
	}
	printf("%d",en);//循环结束输出答案
	return 0;
}

4,一二位前缀和.差分:

一维前缀和:

一维前缀和就是对应一维数组前几项的和,如一个数组a[n](从n=1开始赋值);

s[2]=a[1]+a[2];

s[4]=a[1]+……+a[4];

前缀和数组s[i]=s[i-1]+a[i]

要求一维数组某个区间[l,r]的和就不用在遍历数组,而直接输出s[r]-s[l-1];

二维前缀和:

注意:二维前缀和数组可以从下标为一开始读入数据更方便,但是有的时候题目固定的数组没法处理,但是下标从零开始要加入一些特判条件

#include<bits/stdc++.h>
using namespace std;
const int n=5,m=4;
int x[n][m] = {{4,5,1,3},//需要进行二维前缀和的数组
             {6,2,4,2},
             {4,1,5,7},
             {2,1,6,9},
             {1,3,7,5}},sum[n][m];
void sum1(){
    sum[0][0] = x[0][0];
    for(int i=1;i<m;i++) sum[0][i] = sum[0][i-1]+x[0][i];//求sum数组的第一行
    for(int j=1;j<n;j++) sum[j][0] = sum[j-1][0]+x[j][0];//求sum数组的第一列
    for(int i=1;i<n;i++)//sum数组其他对应数
        for(int j=1;j<m;j++)
            sum[i][j] = x[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];//(公式)理解更方便记忆
}
int get_sum(int x1,int y1,int x2,int y2){
    if(!x1&&!y1) return sum[x2][y2];//如果第一个区间的端点值都为零,直接输出第二个区间的前缀和
    if(!x1)     return sum[x2][y2]-sum[x2][y1-1];//x1为零
    if(!y1)     return sum[x2][y2]-sum[x2-1][y1];//y1为零
    return  sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];//都不为零(公式)
}
int main()
{
  sum1();
  printf("%d",get_sum(1,2,4,3));
  return 0;
}

一维差分:

需要配合一维前缀和来完成,如一个数组a[5]={2,5,6,7,8},先对该数组多个不同区间执行+x操作,如果直接一个一个区间处理就非常耗时间,这时就可以用差分来处理

先写一个空数组b[6] = {0}用于对不同区间加的数的处理,然后对b[]数组求前缀和,此时数组b就是不同区间加过数后的结果,再与数组a每一项对应相加即为所求;对数组b处理主要公式b[r]+x;b[l+1]-x;

但要注意的是数组b最好比a长,不然l+1易溢出或则在执行b[l+1]-x时加个判断;

但此算法只适用多次处理一次或较少次访问

二维差分:

用到了二维前缀和;和一维差分,只不过二维差分需要标记四个位置,即:

d[n1][m1]+=x;

d[n2+1][m1]-=x;

d[n1][m2+1]-=x;

d[n2+1][m2+1]+=x;

int d[n+1][m+1];
int x[n][m] = {{4,5,1,3},
             {6,2,4,2},
             {4,1,5,7},
             {2,1,6,9},
             {1,3,7,5}},sum[n][m];
void sum1(){
    sum[0][0] = d[0][0];
    for(int i=1;i<m;i++) sum[0][i] = sum[0][i-1]+d[0][i]; //对d数组求二维前缀和
    for(int j=1;j<n;j++) sum[j][0] = sum[j-1][0]+d[j][0];
    for(int i=1;i<n;i++)//sum数组其他对应数
        for(int j=1;j<m;j++)
            sum[i][j] = d[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];//(公式)理解更方便记忆
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            x[i][j]+=sum[i][j];//对应相加
}
void add(int n1,int n2,int n3,int n4,int xx)//差分标记
{
	d[n1][n2]+=xx;
	d[n1][n4+1]-=xx;
	d[n3+1][n2]-=xx;
	d[n3+1][n4+1]+=xx;
}
int main()
{
  add(1,2,4,3,5);//需要处理的区间以及需要加减的数
  add(1,2,4,3,5);
  sum1();
  for(int i=0;i<n;i++)
    {
	printf("\n");
        for(int j=0;j<m;j++)//输出结果
        printf("%d ",x[i][j]);
    }
  return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值