1. 程式人生 > >【莫隊】bzoj4866: [Ynoi2017]由乃的商場之旅

【莫隊】bzoj4866: [Ynoi2017]由乃的商場之旅

莫隊的一些套路

Description

由乃有一天去參加一個商場舉辦的遊戲。商場派了一些球王排成一行。每個人面前有幾堆球。說來也巧,由乃和你 一樣,覺得這遊戲很無聊,於是決定換一個商場。另一個商場是Deus的,他看到由乃來了,於是想出了一個更有趣 的遊戲:寫資料結構題這個題是這樣的:   我們的情人,不過是隨便借個名字,用幻想吹出來的肥皂泡,把信拿去吧,你可以使假戲成真。我本來是無病呻吟 ,漫無目的的吐露愛情---現在這些漂泊不定的鳥兒有地方棲息了,你可以從信裡看出來。拿去吧---由於不是出自 真心,話就說得格外動聽,拿去吧,就這麼辦吧...由於世界會在7月20日完結,作為救世主,間宮卓司要在19日讓 所有人迴歸天空現在已經是19日傍晚,大家集合在C棟的天台上,一共n個人在他們面前,便是終之空,那終結的天 空   迴歸天空是一件莊重的事情,所以卓司決定讓大家分批次進行,給每個人給了一個小寫字母'a'->'z'作為編號一個 區間的人如果滿足他們的編號重排之後可以成為一個迴文串,則他們可以一起迴歸天空,即這個區間可以迴歸天空 由於卓司是一個喜歡妄想的人,他妄想了m個區間,每次他想知道每個區間中有多少個子區間可以迴歸天空因為世 界末日要來了,所以卓司的信徒很多   由乃天天做資料結構已經快噁心死了,於是讓您幫她做當然,您天天做資料結構題,肯定也覺得噁心死了,不過可 愛即正義!所以這個題還是要做的~

Input

第一行兩個數n,m 之後一行一個長為n的字串,代表每個人的編號 之後m行每行兩個數l,r代表每次卓司妄想的區間 n,m<=60000

Output

m行,每行一個數表示答案

 

Sample Input

6 6
zzqzzq
1 6
2 4
3 4
2 3
4 5
1 1

Sample Output

16
4
2
2
3
1

題目分析

應該是一類常見套路:考慮每加入一個元素對於已知區間的貢獻。

那麼這裡把每個字母看成$2^i$,先預處理出每一個位置的異或字首和,莫隊查詢時答案增上全為偶次的字元+列舉為奇數的字母的貢獻即可。

注意莫隊中加入與刪除操作的順序,這個有些時候是會相互影響的。

然後用unsigned short int卡空間,就好了。

 1 #include<bits/stdc++.h>
 2 #define S(p) cnt[tmp^(1<<p)]
 3 #define Add(val) tmp=c[val],nw+=cnt[tmp],nw+=S(0)+S(1)+S(2)+S(3)+S(4)+S(5)+S(6)+S(7)+S(8)+S(9)+S(10)+S(11)+S(12)+S(13)+S(14)+S(15)+S(16)+S(17)+S(18)+S(19)+S(20)+S(21)+S(22)+S(23)+S(24)+S(25),++cnt[tmp]
 4
#define Del(val) tmp=c[val],--cnt[tmp],nw-=cnt[tmp],nw-=S(0)+S(1)+S(2)+S(3)+S(4)+S(5)+S(6)+S(7)+S(8)+S(9)+S(10)+S(11)+S(12)+S(13)+S(14)+S(15)+S(16)+S(17)+S(18)+S(19)+S(20)+S(21)+S(22)+S(23)+S(24)+S(25) 5 const int maxn = 70035; 6 const int maxp = 67108900; 7 8 int blk[maxn],size; 9 struct QRs 10 { 11 int l,r,id; 12 bool operator < (QRs a) const 13 { 14 return blk[l]==blk[a.l]?(blk[l]&1?r < a.r:r > a.r):blk[l] < blk[a.l]; 15 } 16 }q[maxn]; 17 int n,m,c[maxn],ans[maxn],L,R,nw,tmp; 18 unsigned short cnt[maxp]; 19 char s[maxn]; 20 21 int read() 22 { 23 char ch = getchar(); 24 int num = 0, fl = 1; 25 for (; !isdigit(ch); ch=getchar()) 26 if (ch=='-') fl = -1; 27 for (; isdigit(ch); ch=getchar()) 28 num = (num<<1)+(num<<3)+ch-48; 29 return num*fl; 30 } 31 int main() 32 { 33 n = read(), m = read(), scanf("%s",s+1); 34 size = std::min(2*(int)sqrt(n+0.5), n)+5; 35 for (int i=1; i<=n; i++) blk[i] = i/size, c[i] = c[i-1]^(1<<(s[i]-'a')); 36 for (int i=1; i<=m; i++) q[i].l = read()-1, q[i].r = read(), q[i].id = i; 37 std::sort(q+1, q+m+1); 38 L = 1, R = 0; 39 for (int i=1; i<=m; i++) 40 { 41 while (L > q[i].l) --L, Add(L); 42 while (R < q[i].r) ++R, Add(R); 43 while (L < q[i].l) Del(L), ++L; 44 while (R > q[i].r) Del(R), --R; 45 ans[q[i].id] = nw; 46 } 47 for (int i=1; i<=m; i++) printf("%d\n",ans[i]); 48 return 0; 49 }

 

 

END