給你乙個長度為n的序列ai,1≤i≤n和q組詢問,每組詢問讀入l1,r1,l2,r2,需輸出
get(l,r,x)表示計算區間[l,r]中,數字x出現了多少次。
input
第一行,乙個數字n,表示序列長度。
第二行,n個數字,表示a1~an
第三行,乙個數字q,表示詢問個數。
第4~q+3行,每行四個數字l1,r1,l2,r2,表示詢問。
n,q≤50000
n1≤ai≤n
1≤l1≤r1≤n
1≤l2≤r2≤n
注意:答案有可能超過int的最大值
output
對於每組詢問,輸出一行乙個數字,表示答案
sample input
51 1 1 1 1
21 2 3 4
1 1 4 4
思路:
我們可以看到這個式子get(l,r,x),我們可以將其分解得到
get(l,r,x)=get(1,r,x)-get(1,l,r),所以我們令s(i)=get(1,i,x);
那麼
又因為所以ans
仔細看分子,實際上就是四個區間中x的數量的平方
(r1,l2),(l1,r2),(l1,l2),(r1,r2)
我們只需要用莫隊維護一下區間x的個數的平方就可以了
**如下:…(* ̄0 ̄)ノ
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const
int mx=
5e4+10;
ll s[mx]
,ans[mx]
,c[mx]
,sum;
//分別為統計區間每個數個數,結果,輸入,和
int tot=
0,cnt;
//分別為p陣列的大小和分塊的大小
struct nodebp[mx<<2]
;bool cmp
(nodeb a,nodeb b)
//分塊排序
void
add(
int k)
//增加操作
void
del(
int k)
//刪除操作
void
put(
int x,
int y,
int a,
int b)
//這裡就是將每次查詢得到四個區間分別弄出來
intmain()
sort
(p+1
,p+1
+tot,cmp)
;//排序
memset
(s,0
,sizeof
(s))
;memset
(ans,0,
sizeof
(ans));
int l=
1,r=0;
sum=0;
for(
int i=
1;i<=tot;i++
)//這裡要記住,add一定是要先增或減,del要後操作
for(
int i=
1;i<=m;i++
)printf
("%lld\n"
,ans[i]
>>1)
;//最後輸出記得除2
return0;
}
bzoj5016 乙個簡單的詢問
這種不可直接做的問題 資料範圍又很小 考慮莫隊 但是,l1,l2,r1,r2四維?考慮把詢問二維差分!f a,b 表示,詢問 1,a 1,b 的答案 所以,ans l1,r1,l2,y2 f r1,r2 f l1 1,r2 f r1,l2 1 f l1 1,l2 1 正確性的話,考慮每乙個種類k被統...
SNOI2017 乙個簡單的詢問
給定乙個長度為 n n le50000 的序列 a 1 le a i le n 定義 operatorname l,r,x 為區間 a 中 x 的出現次數。m m le50000 次詢問,每次給出 l 1,r 1,l 2,r 2 求 sum operatorname l 1,r 1,x cdot o...
洛谷P5268 乙個簡單的詢問
傳送門 to luogu 首先它是個莫隊的題。為什麼?我也不知道 但是莫隊只能處理兩個變數的詢問 並且任意乙個變數的移動對答案的影響可以快速計算,一般是 o 1 mathcal o 1 o 1 所以只好把這個式子變換一下。記 f m x j 1 m aj x f m,x sum a j x f m,...