蓝桥杯训练 | 二分和前缀和 | 02

数的范围

#include<bits/stdc++.h>
using namespace std;

const int N=100000+10;
int q[N];
int n,t;

int bsearch1(int x,int l,int r){
	while(l<r){
		int mid=l+r>>1;
		if(q[mid]>=x)r=mid;
		else l=mid+1;
	}
	return q[l]!=x?-1:l;
}

int bsearch2(int x,int l,int r){
	while(l<r){
		int mid=l+r+1>>1;
		if(q[mid]<=x)l=mid;
		else r=mid-1;
	}
	return q[l]!=x?-1:l;
}
int main(){

	cin >> n >> t;
	for(int i=0;i<n;i++)cin>>q[i];
	while(t--){
		int x;
		cin >> x;
		printf("%d %d",bsearch1(x,0,n-1),bsearch2(x,0,n-1));
	}	
	
	
	return 0;
} 

数的三次方根

#include<bits/stdc++.h>
using namespace std;


int main(){
	double x;
	cin >> x;
	double l=-10000,r=10000,exp=1e-8;
	while(r-l>=exp){
		double mid=(l+r)/2;
		if(pow(mid,3)<=x)l=mid;
		else r=mid;
	}
	printf("%.6lf\n",l);
	
	return 0;
}

前缀和

#include<bits/stdc++.h>
using namespace std;

const int N=100000+10;
int q[N],s[N];

int main(){
	int n,T;
	cin >> n >> T;
	for(int i=1;i<=n;i++){
		cin >> q[i];
		s[i]=s[i-1]+q[i];
	}
	while(T--){
		int l,r;
		cin >> l >> r;
		cout << (s[r]-s[l-1]) << endl;
	}
	
} 

子矩阵的和

#include<bits/stdc++.h>
using namespace std;

const int N=1000+10;
int n,m,T,q[N][N],s[N][N];

int main(){
	scanf("%d%d%d",&n,&m,&T);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%d",&q[i][j]);
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+q[i][j];
		}
	}
	
	while(T--){
		int x1,y1,x2,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		int res = s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
		printf("%d\n",res);
	}
	
	
	return 0;
} 

机器人跳跃问题

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int h[N],n;

bool check(int x){
	for(int i=1;i<=n;i++){
		x = 2*x - h[i];
		if(x<0)return false;
		if(x>1e5)return true;
	}
	return true;
}

int main(){
	cin >> n;
	for(int i=1;i<=n;i++)scanf("%d",&h[i]);
	int l=0,r=1e5;
	while(l<r){
		int mid = l + r >> 1;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	cout << l << endl;
	
	return 0;
} 

四平方和

三重循环的做法

#include<bits/stdc++.h>
using namespace std;

int main(){
    int x;
    cin >> x;
    for(int a=0;a*a<=x;a++){
        for(int b=a;a*a+b*b<=x;b++){
            for(int c=b;a*a+b*b+c*c<=x;c++){
                int dd = x - a*a - b*b - c*c; // dd是d**2
                double d = sqrt(dd);
                if(d==(int)d){
                    printf("%d %d %d %d\n",a,b,c,(int)d);
                    return 0;
                }
            }
        }
    }
    
    return 0;
}

哈希表做法

#include<bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;

unordered_map<int,PII> S;

int main(){
    int x;
    cin >> x;
    for(int c=0;c*c<=x;c++){
        for(int d=c;c*c+d+d<=x;d++){
            int t= c*c + d*d;
            if(S.count(t)==0)S[t]={c,d};
        }
    }
    
    for(int a=0;a*a<=x;a++){
        for(int b=a;a*a+b*b<=x;b++){
            int t = x - a*a - b*b;
            if(S.count(t)){
                printf("%d %d %d %d\n",a,b,S[t].first,S[t].second);
                return 0;
            }
        }
    }
    
    return 0;
}

分巧克力

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int h[N],w[N];
int n,k;


bool check(int x){
	int s=0;
	for(int i=0;i<n;i++){
		s+=(h[i]/x)*(w[i]/x);
		if(s>=k)return true;	
	}
	return s>=k;
}

int main(){
	cin >> n >> k;
	for(int i=0;i<n;i++){
		scanf("%d%d",&h[i],&w[i]);
	}
	int l=1,r=1e5;
	while(l<r){
		int mid=l+r+1>>1;
		if(check(mid))l=mid;
		else r=mid-1;
	}
	cout << l << endl;
	return 0;
} 

激光炸弹

#include<bits/stdc++.h>
using namespace std;

const int N=5000+10;
int s[N][N];

int main(){
	int T,r;
	cin >> T >> r;
	int xx=r,yy=r; // 边界 
	while(T--){
		int x,y,w;
		cin >> x >> y >> w;
		x++,y++;
		xx=max(xx,x),yy=max(yy,y);
		s[x][y]+=w; 
	}
	
	// 预处理前缀和
	for(int i=1;i<=xx;i++){
		for(int j=1;j<=yy;j++){
			s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
		}
	} 
	
	int res = -(1<<30);
	for(int i=r;i<=xx;i++){
		for(int j=r;j<=yy;j++){
			res = max(res,s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r]);
		}
	}
	
	cout << res << endl;
	
	return 0;
} 

K倍区间


O(n**2)做法

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int s[N];
int main(){
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        s[i]+=s[i-1];
    }
    
    int res=0;
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            int t=s[j]-s[i-1];
            if(t%k==0)res++;
        }
    }
    
    cout << res << endl;
    
    return 0;
}

O(n)做法

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N=1e5+10;
LL s[N],cnt[N];

int main(){
    int n,k;
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        scanf("%ld",&s[i]);
        s[i]+=s[i-1];
    }
    
    LL res=0;
    cnt[0]=1;
    for(int i=1;i<=n;i++){ // 枚举右端点
        res+=cnt[s[i]%k];
        cnt[s[i]%k]++;
        
    }
    
    cout << res << endl;
    
    return 0;
}
posted @ 2020-11-29 09:43  RowryCho  阅读(118)  评论(0编辑  收藏  举报