【BZOJ】3781 小B的詢問 莫隊

題目傳送門

有了上一題的鋪墊,這題就是一道莫隊的裸題,直接用和上一題一樣的套路搞就行了。

不過莫隊的sort好像有些什麼神奇的trick:如果兩個詢問左端點所在的塊相同,就把右端點按左端點所在塊的奇偶性分類排序,就是下面那樣:(至於爲什麼,我也不知道)

    bool operator < (const note lyf) const {return (wz[l]<wz[lyf.l])||(wz[l]==wz[lyf.l]&&(wz[l]&1?r<lyf.r:r>lyf.r));}

剩下的就是和上一題差不多的莫隊了。

附上AC代碼:

#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N=5e4+10;
int n,m,k,size,c[N],wz[N];
struct note{
    int l,r,pos;
    bool operator < (const note lyf) const {return (wz[l]<wz[lyf.l])||(wz[l]==wz[lyf.l]&&(wz[l]&1?r<lyf.r:r>lyf.r));}
}a[N];
ll ans,out[N],s[N];

inline char nc(void){
    static char ch[100010],*p1=ch,*p2=ch;
    return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &a){
    static char c=nc();int f=1;
    for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
    for (a=0;isdigit(c);a=(a<<3)+(a<<1)+c-'0',c=nc());
    a*=f;return;
}

inline void updata(int x,int w){return (void)(ans+=s[c[x]]*2ll*w+1,s[c[x]]+=1ll*w);}

int main(void){
    read(n),read(m),read(k),size=sqrt(n);
    for (int i=1; i<=n; ++i) read(c[i]),wz[i]=(i-1)/size+1;
    for (int i=1; i<=m; ++i) read(a[i].l),read(a[i].r),a[i].pos=i;
    sort(a+1,a+1+m);
    for (int i=1,l=1,r=0; i<=m; ++i){
        for (; r<a[i].r; ++r) updata(r+1,1);
        for (; r>a[i].r; --r) updata(r,-1);
        for (; l<a[i].l; ++l) updata(l,-1);
        for (; l>a[i].l; --l) updata(l-1,1);
        out[a[i].pos]=ans;
    }
    for (int i=1; i<=m; ++i) printf("%lld\n",out[i]);
    return 0;
}
發佈了197 篇原創文章 · 獲贊 19 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章