E-前缀和
链接:https://ac.nowcoder.com/acm/contest/332/E
来源:牛客网
题目描述
有一个沿海地区,可以看作有n行m列的城市,第i行第j列的城市海拔为h[i][j]。
由于沿海,所以这个地区经常会发生海啸。
海啸发生时,部分城市会被淹没,具体来说,海水高度会达到d,因此海拔低于d的城市都会被淹没。
现在有q次询问,每次问你一个矩形区域中,有多少城市不会被淹没。
输入描述:
第一行三个整数n,m,d,具体含义见题目描述。
接下来n行,每行m个整数,其中第i行第j列的整数为h[i][j],具体含义见题目描述。
第n+2行一个整数q,表示询问数。
接下来q行,每行四个整数a,b,x,y,
表示询问从第a行第b列到第x行第y列的矩形地区中,有多少地区不会被淹没。
即有多少个i,j,满足 a≤i≤x,b≤j≤y ,且 h[i][j]≥d 。
输出描述:
共q行,第i行一个整数,表示第i个询问的答案。
示例1
输入
3 3 3
1 2 3
2 1 5
4 3 2
2
1 2 2 3
2 1 3 3
输出
2
3
备注:
1≤n×m≤10^6
1≤q≤10^5
0≤d,h[i][j]≤10^9
1≤a≤x≤n,1≤b≤y≤m
解题思路:
前缀和
代码:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch>'9'||ch<'0')f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return f?-x:x;
}
const int maxn=1e6+3;
int mp[maxn],bit[maxn],n,m,d;
int lowbit(int x){return x&-x;}
inline void add(int x,int y,int num){
for(int i=x;i<=n;i+=lowbit(i))for(int j=y;j<=m;j+=lowbit(j))bit[i*m-m+j]+=num;
}
inline int sum(int a,int b){
int ans=0;
for(int i=a;i;i-=lowbit(i))for(int j=b;j;j-=lowbit(j))ans+=bit[i*m-m+j];
return ans;
}
int main(){
n=read(),m=read(),d=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(read()>=d)add(i,j,1);
int q=read();
while(q--){
int lu=read(),ru=read(),ld=read(),rd=read();
printf("%d\n",sum(ld,rd)-sum(lu-1,rd)-sum(ld,ru-1)+sum(lu-1,ru-1));
}
return 0;
}
G-找规律
链接:https://ac.nowcoder.com/acm/contest/332/G
来源:牛客网
题目描述
求a|(a+1)|(a+2)|…|(b-1)|b。
其中|表示按位或。
输入描述:
多组输入,每行两个数表示a和b
输出描述:
对于每组输入,输出一个数a|(a+1)|(a+2)|…|(b-1)|b。
示例1
输入
99 109
68 77
55 66
34 43
1111234 1114321
输出
111
79
127
47
1179647
备注:
输入不超过10000行,
0≤a,b≤10^18,a≤b
解题思路:
二进制下,比较l,r两数第一个不同的位置,后面都变成1
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll l,r;
while(~scanf("%lld%lld",&l,&r)){
if(l==r-1){
printf("%lld\n",l|r);
continue;
}
int p=log2(r);
for(int i=p;i>=0;--i){
if(((l>>i)&1)==((r>>i)&1))continue;
r|=((1ll<<i)-1);
break;
}
printf("%lld\n",r);
}
return 0;
}