1. 程式人生 > >P4113 [HEOI2012]采花 (莫隊TLE)

P4113 [HEOI2012]采花 (莫隊TLE)

pri dao printf 連續 愛好 const algorithm efi 整數

P4113 [HEOI2012]采花

題目描述

蕭薰兒是古國的公主,平時的一大愛好是采花。
今天天氣晴朗,陽光明媚,公主清晨便去了皇宮中新建的花園采花。
花園足夠大,容納了n朵花,花有c種顏色(用整數1-c表示),且花是排成一排的,以便於公主采花。公主每次采花後會統計采到的花的顏色數,顏色數越多她會越高興!同時,她有一癖好,她不允許最後自己采到的花中,某一顏色的花只有一朵。為此,公主每采一朵花,要麽此前已采到此顏色的花,要麽有相當正確的直覺告訴她,她必能再次采到此顏色的花。
由於時間關系,公主只能走過花園連續的一段進行采花,便讓女仆福涵潔安排行程。福涵潔綜合各種因素擬定了m個行程,然後一一向你詢問公主能采到多少朵花(她知道你是編程高手,定能快速給出答案!),最後會選擇令公主最高興的行程(為了拿到更多獎金!)。

輸入輸出格式

輸入格式:
第一行四個空格隔開的整數n、c以及m。接下來一行n個空格隔開的整數,每個數在[1, c]間,第i個數表示第i朵花的顏色。接下來m行每行兩個空格隔開的整數l和r(l ≤ r),表示女仆安排的行程為公主經過第l到第r朵花進行采花。
輸出格式:
共m行,每行一個整數,第i個數表示公主在女仆的第i個行程中能采到的花的顏色數。

輸入輸出樣例

輸入樣例#1:
5 3 5
1 2 2 3 1
1 5
1 2
2 2
2 3
3 5
輸出樣例#1:
2
0
0
1

說明

對於100%的數據,1 ≤ n ≤ \(2*10^6\) ,c ≤ n,m ≤ \(2*10^6\)
本題有兩個subtask


subtask1保證 \(n,m,c \leq 3*10^5\) ,占100分
subtask2保證 \(n,m,c \leq 2*10^6\) ,占100分

本題莫隊過不去,會TLE

但也是個不錯的莫隊練手題

畢竟Chen_Zhe還給了100分莫隊分 (還會給你小對勾)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn    2000007
using namespace std;
inline int read()
{
    int x=0,f=1;char s=getchar();
    while('0'>s||s>'9') {
        if(s=='-') f=-1;
        s=getchar();
    }
    while('0'<=s&&s<='9') {
        x=x*10+s-'0';
        s=getchar();
    }
    return x*f;
}
int n,m,k,now;
int a[maxn];
int belong[maxn];
int vis[maxn];
int ans[maxn]; 
struct node{
    int l,r,id;
}q[maxn];
inline bool cmp(const node &a,const node &b)
{
    return belong[a.l]==belong[b.l] ? a.r<b.r :  belong[a.l]<belong[b.l];
}
inline void Add(int x)
{
    vis[x]==1 ? ++now : now;
    ++vis[x];
}
inline void Delet(int x)
{
    vis[x]==2 ? --now : now;
    --vis[x];
}
int main()
{
    n=read();
    int meiyongdebianliang_qidaotixingfanweidezuoye__233zhemechangdebianliangming=read();
    m=read();   
    k=sqrt(n);
    for(int i=1;i<=n;++i)
        a[i]=read();
    for(int i=1;i<=n;++i)
        belong[i]=(i-1)/k+1;
    for(int i=1;i<=m;++i)
    {
        q[i].l=read();
        q[i].r=read();
        q[i].id=i;  
    }
    sort(q+1,q+1+m,cmp);
    int l=1,r=0;
    for(int i=1;i<=m;++i)
    {
        while(l > q[i].l) Add(a[--l]);
        while(l < q[i].l) Delet(a[l++]);
        while(r < q[i].r) Add(a[++r]);
        while(r > q[i].r) Delet(a[r--]);
        ans[q[i].id]=now; 
    }
    for(int i=1;i<=m;++i) 
        printf("%d\n",ans[i]); 
    return 0;
} 

P4113 [HEOI2012]采花 (莫隊TLE)