1. 程式人生 > >[BZOJ2821]作詩(Poetize)

[BZOJ2821]作詩(Poetize)

gree query return center sqrt style zoj har sample

2821: 作詩(Poetize)

Time Limit: 50 Sec Memory Limit: 128 MB Submit: 3178 Solved: 925 [Submit][Status][Discuss]

Description

神犇SJY虐完HEOI之後給傻×LYD出了一題:SHY是T國的公主,平時的一大愛好是作詩。由於時間緊迫,SHY作完詩 之後還要虐OI,於是SHY找來一篇長度為N的文章,閱讀M次,每次只閱讀其中連續的一段[l,r],從這一段中選出一 些漢字構成詩。因為SHY喜歡對偶,所以SHY規定最後選出的每個漢字都必須在[l,r]裏出現了正偶數次。而且SHY認 為選出的漢字的種類數(兩個一樣的漢字稱為同一種)越多越好(為了拿到更多的素材!)。於是SHY請LYD安排選 法。LYD這種傻×當然不會了,於是向你請教……問題簡述:N個數,M組詢問,每次問[l,r]中有多少個數出現正偶 數次。

Input

輸入第一行三個整數n、c以及m。表示文章字數、漢字的種類數、要選擇M次。第二行有n個整數,每個數Ai在[1, c ]間,代表一個編碼為Ai的漢字。接下來m行每行兩個整數l和r,設上一個詢問的答案為ans(第一個詢問時ans=0), 令L=(l+ans)mod n+1, R=(r+ans)mod n+1,若L>R,交換L和R,則本次詢問為[L,R]。

Output

輸出共m行,每行一個整數,第i個數表示SHY第i次能選出的漢字的最多種類數。

Sample Input

5 3 5
1 2 2 3 1
0 4
1 2
2 2
2 3
3 5

Sample Output

2
0
0
0
1

HINT

對於100%的數據,1<=n,c,m<=10^5

類似於區間眾數的做法

把塊到塊的答案預處理出來,然後在查詢時暴力兩端的數

根據兩端的數在區間出現的次數以及整塊裏的次數來判斷對答案的影響

絕對不要memset,絕對不要!!

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int readint(){
    int n = 0;
    char ch = getchar();
    while(ch < 0 || ch > 
9) ch = getchar(); while(ch <= 9 && ch >= 0){ n = (n << 1) + (n << 3) + ch - 0; ch = getchar(); } return n; } const int maxn = 100000 + 10; int n, c, m; int a[maxn], belong[maxn], block_size; int f[1500][1500], tax[maxn]; inline void work(int x){ int ans = 0; for(int i = (x - 1) * block_size + 1; i <= n; i++) tax[a[i]] = 0; for(int i = (x - 1) * block_size + 1; i <= n; i++){ tax[a[i]]++; if((tax[a[i]] & 1) && tax[a[i]] != 1) ans--; if(!(tax[a[i]] & 1)) ans++; f[x][belong[i]] = ans; } } struct Node{int pos, val;}no[maxn]; inline bool cmp(const Node &a, const Node &b){ return a.val == b.val ? a.pos < b.pos : a.val < b.val; } int first[maxn], last[maxn]; inline int upper(int x, int k){ int l = first[x], r = last[x], mid, ret = 0; while(l <= r){ mid = l + r >> 1; if(no[mid].pos > k) r = mid - 1; else{ ret = mid; l = mid + 1; } } return ret; } inline int lower(int x, int k){ int l = first[x], r = last[x], mid, ret = 66662333; while(l <= r){ mid = l + r >> 1; if(no[mid].pos < k) l = mid + 1; else{ ret = mid; r = mid - 1; } } return ret; } inline int Count(int l, int r, int x){ return max(upper(x, r) - lower(x, l) + 1, 0); } bool mark[maxn] = {false}; inline int Query(int l, int r){ int ans = 0; if(belong[r] - belong[l] <= 1){ for(int t, i = l; i <= r; i++){ if(mark[a[i]]) continue; mark[a[i]] = true; t = Count(l, r, a[i]); if(!(t & 1) && t) ans++; } for(int i = l; i <= r; i++) mark[a[i]] = false; return ans; } else{ int ll = belong[l] * block_size + 1, rr = (belong[r] - 1) * block_size; ans = f[belong[ll]][belong[rr]]; for(int x, y, i = l; i < ll; i++){ if(mark[a[i]]) continue; mark[a[i]] = true; x = Count(l, r, a[i]); y = Count(ll, rr, a[i]); if((x & 1)){ if(!(y & 1) && y) ans--; } else if(x && (!y || (y & 1))) ans++; } for(int x, y, i = rr + 1; i <= r; i++){ if(mark[a[i]]) continue; mark[a[i]] = true; x = Count(l, r, a[i]); y = Count(ll, rr, a[i]); if((x & 1)){ if(!(y & 1) && y) ans--; } else if(x && (!y || (y & 1))) ans++; } for(int i = l; i < ll; i++) mark[a[i]] = false; for(int i = rr + 1; i <= r; i++) mark[a[i]] = false; return ans; } } int main(){ n = readint(); c = readint(); m = readint(); block_size = 1.0 * n / sqrt(log2(n + 1) * m); for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block_size + 1; for(int i = 1; i <= n; i++){ no[i].val = a[i] = readint(); no[i].pos = i; } sort(no + 1, no + n + 1, cmp); for(int i = 1; i <= n; i++){ if(!first[no[i].val]) first[no[i].val] = i; last[no[i].val] = i; } for(int i = 1; i <= n; i++) work(i); for(int l, r, ans = 0, i = 1; i <= m; i++){ l = (readint() + ans) % n + 1; r = (readint() + ans) % n + 1; if(l > r) swap(l, r); printf("%d\n", ans = Query(l, r)); } return 0; }

[BZOJ2821]作詩(Poetize)