距离4月13号蓝桥杯还有22天,内容仅供参考,不足之处望理解
AcWing 3745. 牛的学术圈 I
二分+双指针(AC):
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,l,a[N],ans,flag;
bool check(int x){
ans=0,flag=0;
for(int i=n;i>=1;i--){
if(a[i]>=x){
if(a[i]>=x+1) ans++;//ans记录数值>=x+1的数目
else flag++; //flag记录数值恒为x的数目
}
else break;
}
//ans+flag记录的是数值>=x的数目
if(ans+flag>=x) return true;
else return false;
}
int main(){
//输入后排序
cin>>n>>l;
for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1);
//开始二分查找
int left=0,right=2*n;
while(left<right){
int mid=(left+right+1)/2;
if(check(mid)) left=mid;
else right=mid-1;
}
//查找完后要再次查找,来更新ans和flag
int temp=check(left);
//min(flag,l)表示加上l个1之后,新增数值为x+1的数目
//因此ans+min(flag,l)表示加上l个1之后,所有数值>=x+1的数目
if(ans+min(flag,l)>=left+1) cout<<left+1<<endl;
else cout<<left<<endl;
return 0;
}
AcWing 1238. 日志统计(第九届省赛)
暴力 未AC(56 points):
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+5;
int n,d,k,cnt[N];
struct tsid{
int ts,id;
}a[N];
bool cmp(tsid x,tsid y){
if(x.id==y.id){
return x.ts<y.ts;
}
return x.id<y.id;
}
void judge(int l,int r){
//清空cnt
memset(cnt,0,sizeof(cnt));
//存储cnt
for(int i=l;i<=r;i++) cnt[a[i].ts]++;
//暴力记录
int ans=0;
for(int i=a[l].ts;i<=a[r].ts;i++){
int temp=0;
for(int j=i;j<=i+d-1;j++) temp+=cnt[j];
ans=max(ans,temp);
}
//输出
if(ans>=k) cout<<a[l].id<<endl;
}
int main(){
ios::sync_with_stdio(false);
//输入
cin>>n>>d>>k; for(int i=1;i<=n;i++) cin>>a[i].ts>>a[i].id;
//以id为优先从小到大排序
sort(a+1,a+n+1,cmp);
int i=1;
while(i<=n){
int t=a[i].id,startt=i;
while(i++){
if(a[i].id!=t){
//判断每一个id
judge(startt,i-1);
break;
}
}
}
return 0;
}
双指针(AC):
#include<iostream>
#include<algorithm>
#define x first
#define y second
using namespace std;
const int N=1e5+5;
typedef pair<int,int> pii;
pii a[N];
int n,d,k,cnt[N];
bool flag[N];
int main(){
ios::sync_with_stdio(false);
//输入
cin>>n>>d>>k;
for(int i=0;i<n;i++) {cin>>a[i].x>>a[i].y;}
//以时间为优先排序
sort(a,a+n);
//i未快指针依次遍历数据,j为慢指针在i指针的后面
for(int i=0,j=0;i<n;i++){
//每次遇见点赞的贴子,计数数组自增
int temp=a[i].y;
cnt[temp]++;
//当超过时间距离时,计数数组自减,j指针自增移动
while(a[i].x-a[j].x>=d){
cnt[a[j].y]--;
j++;
}
//只要发现计数的数目>=k,就标记flag数组
if(cnt[temp]>=k) flag[temp]=true;
}
//输出有标记的下标
for(int i=0;i<1e5;i++) if(flag[i]) cout<<i<<endl;
return 0;
}
AcWing 4405. 统计子矩阵(第十三届省赛)
暴力 未AC(64points):
#include<iostream>
using namespace std;
const int N=505;
int n,m,t,a[N][N];
int main(){
ios::sync_with_stdio(false);
//输入
cin>>n>>m>>t;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
//二维前缀和
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
//暴力枚举
long long cnt=0;
for(int i=1;i<=n;i++){ //下边界
for(int j=1;j<=m;j++){ //右边界
for(int k=1;k<=i;k++){ //上边界
for(int l=1;l<=j;l++){ //左边界
//判断后计数
if((a[i][j]+a[k-1][l-1]-a[k-1][j]-a[i][l-1])<=t)
cnt++;
}
}
}
}
cout<<cnt<<endl;
return 0;
}
一维前缀和+双指针(AC):
#include<iostream>
using namespace std;
const int N=505;
int n,m,t,a[N][N];
int main(){
ios::sync_with_stdio(false);
cin>>n>>m>>t;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
//以列做一维前缀和
a[i][j]+=a[i-1][j];
}
}
long long cnt=0;
for(int i=1;i<=n;i++){ //上边界
for(int j=i;j<=n;j++){ //下边界
long long sum=0;
//left不动,先遍历right
for(int left=1,right=1,sum=0;right<=m;right++){
//每次sum加上一列
sum+=a[j][right]-a[i-1][right];
//当sum>t时,说明right无需继续移动,left开始移动
while(sum>t){
//把最左侧的一列减去
sum-=a[j][left]-a[i-1][left];
//移动left
left++;
}
//计数器计数
cnt+=right-left+1;
}
}
}
cout<<cnt<<endl;
return 0;
}