1. 程式人生 > >P2709 小B的詢問 莫隊

P2709 小B的詢問 莫隊

include queue temp template int set n) iostream 明顯

這個題,莫隊很容易想到(格式很明顯),然後直接用數學公式維護一下和就行了。

題幹:

題目描述
小B有一個序列,包含N個1~K之間的整數。他一共有M個詢問,每個詢問給定一個區間[L..R],求Sigma(c(i)^2)的值,其中i的值從1到K,其中c(i)表示數字i在[L..R]中的重復次數。小B請你幫助他回答詢問。
輸入輸出格式
輸入格式:
第一行,三個整數N、M、K。
第二行,N個整數,表示小B的序列。
接下來的M行,每行兩個整數L、R。
輸出格式:
M行,每行一個整數,其中第i行的整數表示第i個詢問的答案

代碼:

#include<iostream>
#include
<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;i++) #define lv(i,a,n) for(register int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const
int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < 0 || c > 9) if(c == -) op = 1; x = c - 0; while(c = getchar(), c >= 0 && c <=
9) x = x * 10 + c - 0; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar(-), x = -x; if(x >= 10) write(x / 10); putchar(0 + x % 10); } struct node { int l,r,id,pos; }a[50005]; int blo,n,m,k; ll b[50005],num[56000]; ll cnt[50005]; bool cmp(node a,node b) { if(a.pos != b.pos) return a.pos < b.pos; else return a.r < b.r; } int main() { read(n);read(m);read(k); blo = sqrt(n); duke(i,1,n) { read(b[i]); } duke(i,1,m) { read(a[i].l); read(a[i].r); a[i].id = i; a[i].pos = (a[i].l - 1) / blo + 1; } sort(a + 1,a + m + 1,cmp); int l = 1,r = 0; ll ans = 0; duke(i,1,m) { while(l > a[i].l) l--,cnt[b[l]]++,ans += 2 * cnt[b[l]] - 1; while(r < a[i].r) r++,cnt[b[r]]++,ans += 2 * cnt[b[r]] - 1; while(l < a[i].l) cnt[b[l]]--,ans -= 2 * cnt[b[l]] + 1,l++; while(r > a[i].r) cnt[b[r]]--,ans -= 2 * cnt[b[r]] + 1,r--; num[a[i].id] = ans; } duke(i,1,m) { printf("%lld\n",num[i]); } return 0; }

P2709 小B的詢問 莫隊