7.31错题总结

· · 个人记录

T3(B3667 求区间所有后缀最大值的位置)

考试思路:单调模板题

考试代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1000005],m;
deque<int>q;
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        while(!q.empty()&&q.front()+m<=i)
            q.pop_front();
        while(!q.empty()&&a[q.back()]<=a[i])
            q.pop_back();
        q.push_back(i);
        if(i>=m)
            cout<<q.size()<<'\n';
    }
    return 0;
}

错误原因:第二个while循环不用刷掉和a[i]相同的

正确思路:还是单调模板题

正确代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1000005],m;
deque<int>q;
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        while(!q.empty()&&q.front()+m<=i)
            q.pop_front();
        while(!q.empty()&&a[q.back()]<a[i])
            q.pop_back();
        q.push_back(i);
        if(i>=m)
            cout<<q.size()<<'\n';
    }
    return 0;
}

T6(P2564 [SCOI2009] 生日礼物)

考试思路:二分查找

考试代码:

  #include<bits/stdc++.h>
#define int long long
using namespace std;
struct N
{
    int id,wz;
}a[1000005];
int n,k,ans;
map<int,int>mp;
bool cmp(N x,N y)
{
    return x.wz<y.wz;
}
bool check(int x)
{
    mp.clear();
    int sum=0;
    for(int i=1;i<x;i++)
    {
        mp[a[i].wz]++;
        if(mp[a[i].wz]==1)
            sum++;
    }
    for(int i=x;i<=n;i++)
    {
        mp[a[i].wz]++;
        if(mp[a[i].wz]==1)
            sum++;
        if(i!=x)
        {
            mp[a[i-x].wz]--;
            if(mp[a[i-x].wz]==0)
                sum--;
        }
        if(sum==k)
        {
            ans=min(ans,x);
            return 1;
        }
    }
    return 0;
}
deque<int>q;
signed main()
{
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        int x;
        cin>>x;
        for(int j=1;j<=x;j++)
        {
            int z;
            cin>>z;
            a[++ans].id=x;
            a[ans].wz=z;
        }
    }
    sort(a+1,a+n+1,cmp);
    ans=1e9;
    int l=1-1,r=n+1;
    while(l+1<r)
    {
        int mid=(l+r)/2;
        if(check(mid)==1)
            r=mid;
        else
            l=mid;
    }
    cout<<ans;
    return 0;
}

错误原因:时间爆炸了

正确思路:不二分了,直接模拟单调队列

正确代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct N
{
    int id,wz;
}a[1000005];
bool cmp(N x,N y)
{
    return x.wz<y.wz;
}
map<int,int>mp;
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,k,l=1,mn=INT_MAX,cnt=0,sum=0;
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        int x;
        cin>>x;
        for(int j=1;j<=x;j++)
        {
            int y;
            cin>>y;
            a[++cnt]={i,y};
        }
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        mp[a[i].id]++;
        if(mp[a[i].id]==1)
            sum++;
        while(i!=l&&mp[a[l].id]>1)
        {
            mp[a[l].id]--;
            l++;
        }
        if(sum==k)
            mn=min(a[i].wz-a[l].wz,mn);
    }
    cout<<mn<<'\n';
    return 0;
}