小b有乙個序列,包含n個1~k之間的整數。他一共有m個詢問,每個詢問給定乙個區間[l..r],求$\sum_1^kc_i^2$的值,其中$c_i$表示數字i在[l..r]中的重複次數。小b請你幫助他回答詢問。
輸入格式:
第一行,三個整數n、m、k。
第二行,n個整數,表示小b的序列。
接下來的m行,每行兩個整數l、r。
輸出格式:
m行,每行乙個整數,其中第i行的整數表示第i個詢問的答案。
輸入樣例#1:
6 4 31 3 2 1 1 3
1 42 6
3 55 6
輸出樣例#1:
6952
對於全部的資料,1<=n、m、k<=50000
bzoj居然把這題設成許可權題,我們這種窮人做不起啊,放個題號吧。
我的**在洛谷上跑的挺快,剛開始沒開o2,跑了1900+ms,然後去大牛分站交了一波,瞬間540毫秒,rank3了啊!估計我的程式最大的耗時處在兩個sort上,algorithm裡的東西和stl裡的東西缺氧,吸了氧就跑得飛快,幾乎是缺氧時的四倍速度了。
後來加快讀、乘法換成位運算、另開乙個陣列$o(m)$記錄答案而不是第二次排序,尤其是最後一項,整整少了60ms,終於卡到了473ms,目前的洛谷rank1.
一道裸的莫隊。莫隊的原理可以看我這篇博文,每個莫隊題目最重要的步驟都是推導出區間中減少乙個元素或加入乙個元素後答案的變化。
這題推公式不難。設當前區間$[l,r]$的答案為$t$,那麼增加(l--或r++)乙個元素時,設增加元素的顏色為k (l-1或r+1),$f(k)$為題目中的$c(k)$,那麼$t+=(f(k)+1)^2-f^2(k)=2*f(k)+1$,同理,減少乙個顏色為k的元素時$t-=f^2(k)-(f(k)-1)^2=2*f(k)-1$,於是就套上莫隊的標誌「四個while」吧。
#include#include#include
using
namespace
std;
inline
intget
()int
n,m,k;
int c[50010]=;
int f[50010]=;
struct
querya[
50010
];int aa[50010]=;
inline
int cmp1(const query & a,const query &b)
intmain()
; }
sort(a+1,a+1+m,cmp1);
for(int i=1,l=0,r=0,t=0;i<=m;i++)
while(lwhile(l>a[i].l)
while(r>a[i].r)
a[i].ans=t;
}for(int i=1;i<=m;i++) aa[a[i].id]=a[i].ans-1
;
for(int i=1;i<=m;i++) printf("
%d\n
",aa[i]);
return0;
}
洛谷P2709 小B的詢問
傳送門 題目描述 小b有乙個序列,包含n個1 k之間的整數。他一共有m個詢問,每個詢問給定乙個區間 l.r 求sigma c i 2 的值,其中i的值從1到k,其中c i 表示數字i在 l.r 中的重複次數。小b請你幫助他回答詢問。輸入輸出格式 輸入格式 第一行,三個整數n m k。第二行,n個整數...
洛谷P2709 小B的詢問
題目描述 小b有乙個序列,包含n個1 k之間的整數。他一共有m個詢問,每個詢問給定乙個區間 l.r 求sigma c i 2 的值,其中i的值從1到k,其中c i 表示數字i在 l.r 中的重複次數。小b請你幫助他回答詢問。輸入輸出格式 輸入格式 第一行,三個整數n m k。第二行,n個整數,表示小...
洛谷 P2709 小B的詢問
莫隊演算法,弄兩個指標亂搞即可 這應該是基礎莫隊了吧 x 2 可以拆成 x 1 1 2 也就是 x 1 2 1 2 2 times x 1 那麼如果乙個數字出現的次數修改 1 那麼 ans 1 2 times sum a pos 1 sum a pos 表示出現在 pos 位置上的數出現的次數。反之...