Acwing2024蓝桥杯双指针

距离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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值