[JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

题目链接:

http://172.16.0.132/senior/#main/show/4307

题目:

解题报告:

题目询问我们没出现坏对的连续区间个数

我们考虑从左到有枚举右端点$r$,判断$a[r]$是否在当前的区间中形成了坏对,如果有的话就$l++$。每次就累加上$r-l+1$,表示左端点取$[l,r]$都可以

考虑维护一个桶来快速判断是否存在坏对

时间复杂度没仔细算

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;

const int N=1e5+15;
int n,k;
ll ans;
int a[N],tong[N];
inline int read()
{
    char ch=getchar();
    int s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
int main()
{
    freopen("drink.in","r",stdin);
    freopen("drink.out","w",stdout);
    n=read();k=read();
    for (int i=1;i<=n;i++) a[i]=read();
    int mx=0,l=1,r=1;
    while (r<=n)
    {
        if (a[r]>=k)
        {
            for (int j=0;j<=mx;j++)
            {
                int t=a[r]*j+k;
                if (t>mx) break;
                while (tong[t]) --tong[a[l++]];
            }
        }
        mx=max(mx,a[r]);
        ++tong[a[r]];
    //    printf("%d %d\n",r,r-l+1);
        ans+=r-l+1;
        ++r;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xxzh/p/9787583.html