codeforces 338e

題意:根據僞代碼 求出答案

思路:其實他要我們求的是一個符合他條件 a[] 的連續的子串有多少個 這個字串必須滿足一個條件 就是經過和b[]任意的匹配後 每一對數之和需要大於等於 一個特定的值  那麼 最優的方案就是貪心  子串最大的 和  最小的b[]的匹配 第二大和第二小的 。。。。 如此匹配 雖然源代碼得到的最後匹配不是這個 但是如果不滿足這個方案 就肯定無解

對於每個a[] 我們可以從b[]中知道在他可以匹配的最小b[]是多少 記位置爲x 那麼b[]  x 到 m 小的值都可以匹配 於是用線段樹來進行區間更新


ps:想到用區間更新了 但是以爲自己想的那樣會超時  結果就沒寫出來  看來別人代碼才知道  底子不紮實 自己騙自己 


#include<cstring>
#include<cstdlib>
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define N 150010
#define MOD 1000000009
#define LL long long

int a[N];
int b[N];
int c[N*4];
int p[N*4];
int q[N*4];

int n,m,k;

void update(int tt)
{
    c[tt*2]+=p[tt];c[tt*2+1]+=p[tt];
    p[tt*2]+=p[tt];p[tt*2+1]+=p[tt];
    p[tt]=0;
}

void change(int l,int r,int tt,int x,int y,int k)
{
    if(l==x&&r==y)
    {
        c[tt]+=k;
        p[tt]+=k;
        return ;
    }
    update(tt);
    int mid=(l+r)/2;
    if(x>mid)change(mid+1,r,tt*2+1,x,y,k);
    else if(y<=mid)change(l,mid,tt*2,x,y,k);
    else
    {
        change(mid+1,r,tt*2+1,mid+1,y,k);
        change(l,mid,tt*2,x,mid,k);
    }
    c[tt]=min(c[tt*2],c[tt*2+1]);
}

int fd(int x)
{
    int l=1,r=m,ret=m+1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(x+a[mid]>=k)
        {
            ret=mid;
            r=mid-1;
        }
        else
        {
            l=mid+1;
        }
    }
    return ret;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a[i]);
    }
    sort(a+1,a+m+1);
    for(int i=1;i<=m;i++) change(1,m,1,i,i,-i);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);
        q[i]=fd(b[i]);
        if(q[i]<=m)change(1,m,1,q[i],m,1);
        if(i>m&&q[i-m]<=m)change(1,m,1,q[i-m],m,-1);
        ans+=c[1]>=0;
    }
    printf("%d\n",ans);
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章