【bzoj 3809】Gty的二逼妹子序列 题解&代码(c++)

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=3809

题解:
bzoj脸太黑,蜜汁超时,具体算法是莫队+分块,唉

代码:(超时的代码)

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<math.h>
#define maxn (100005)
#define maxm (1000005)
using namespace std;
int len;
struct node{
    int l,r;
    int a,b;
    int id;
}q[maxm];
int cmp(node x,node y)
{
    int idx=x.l/len;
    int idy=y.l/len;
    if (idx!=idy)
    return idx<idy;
    else return x.r<y.r;
}
int n,m,s[maxn],ans[maxm],sq[maxn],cnt[maxn],k[maxn];
int f(int x,int y)
{
    int ans=0;
    int X=sq[x];
    int Y=sq[y];
    if (sq[x]==sq[y])
    {
        for (int i=x;i<=y;i++)
        if (cnt[i]>0)   ans++;
        return ans;
    }
    while(X==sq[x])
    {
        if (cnt[x]>0) ans++;
        x++;
    }
    while(Y==sq[y])
    {
        if (cnt[y]>0) ans++;    
        y--;
    }
    for (int i=sq[x];i<=sq[y];i++) ans+=k[i];
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    scanf("%d",&s[i]);
    len=sqrt(n);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b);
        q[i].id=i;
    }
    for (int i=1;i<=n;i++)
    sq[i]=(i-1)/len+1;

    sort(q+1,q+1+m,cmp);

    int nowL=0,nowR=0;
    for (int i=1;i<=m;i++)
    {
        node now=q[i];
        while (now.l > nowL)
        {
            cnt[s[nowL]]--;
            if (cnt[s[nowL]]==0) k[sq[s[nowL]]]--;
            nowL++;
        }
        while(now.l < nowL)
        {
            nowL--;
            cnt[s[nowL]]++;
            if (cnt[s[nowL]]==1) k[sq[s[nowL]]]++;
        }
        while(now.r < nowR)
        {
            cnt[s[nowR]]--;
            if (cnt[s[nowR]]==0) k[sq[s[nowR]]]--;
            nowR--;
        }
        while(now.r > nowR)
        {
            nowR++;
            cnt[s[nowR]]++;
            if (cnt[s[nowR]]==1) k[sq[s[nowR]]]++;
        }
        ans[now.id]=f(now.a,now.b);
    }
    for (int i=1;i<=m;i++)
    printf("%d\n",ans[i]);
} 

你可能感兴趣的:(分块,bzoj,莫队)