您的位置:首页 > 其它

BZOJ 2724: [Violet 6]蒲公英( 分块 )

2015-11-23 17:42 393 查看


虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢...

无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和,事实上我是写后缀和..因为下标从0开始..), cnt[i][j][k]表示第i块中的前j个数中,k出现次数。预处理O(N1.5), 询问每次O(N0.5), 总O((N+M)N0.5)

-------------------------------------------------------------------

#include<cstdio>

#include<cstring>#include<algorithm>#include<cmath>#include<cctype> using namespace std; typedef pair<int, int> pii; const int maxb = 209;const int maxn = 40009; struct HASH { int h[maxn], n; HASH() : n(0) { } void Add(int v) { h[n++] = v; } void Work() { sort(h, h + n); n = unique(h, h + n) - h; } inline int Hash(int v) { return lower_bound(h, h + n, v) - h; } inline int _Hash(int v) { return h[v]; } } H; int read() { char c = getchar(); int ret = 0; for(; !isdigit(c); c = getchar()) c = getchar(); for(; isdigit(c); c = getchar()) ret = ret * 10 + c - '0'; return ret;} int seq[maxn];int sum[maxb][maxn], cnt[maxb][maxb][maxb], c[maxn], Id[maxb][maxn];int N, Q, B, n;pii Mode[maxb][maxb]; // <numId, cnt> void Init() { N = read(); Q = read(); B = (int) sqrt(N); n = N / B; if(N % B) n++; for(int i = 0; i < N; i++) H.Add(seq[i] = read()); H.Work(); for(int i = 0; i < N; i++) seq[i] = H.Hash(seq[i]); memset(sum, 0, sizeof sum); for(int i = 0; i < N; i++) sum[i / B][seq[i]]++; for(int i = n; i--; ) for(int j = 0; j < H.n; j++) sum[i][j] += sum[i + 1][j]; for(int i = 0; i < n; i++) { memset(c, 0, sizeof c); int Max = 0, numId; for(int j = i; j < n; j++) { int p = j * B; for(int k = 0; k < B; k++, p++) if(++c[seq[p]] > Max) { numId = seq[p]; Max = c[seq[p]]; } else if(c[seq[p]] == Max) { numId = min(numId, seq[p]); } Mode[i][j] = make_pair(numId, Max); } } memset(cnt, 0, sizeof cnt); memset(Id, -1, sizeof Id); for(int i = 0; i < n; i++) { Id[i][H.n] = 0; int p = i * B; for(int j = 0; j < B; j++, p++) { int v = seq[p]; if(!~Id[i][v]) Id[i][v] = Id[i][H.n]++; cnt[i][j][Id[i][v]]++; } for(int j = B; j--; ) for(int k = 0; k < Id[i][H.n]; k++) cnt[i][j][k] += cnt[i][j + 1][k]; }} inline int getSum(int l, int r, int v) { return sum[l][v] - sum[r + 1][v];} inline int getCnt(int Block, int l, int r, int numId) { return cnt[Block][l][Id[Block][numId]] - cnt[Block][r + 1][Id[Block][numId]];} int solve(int l, int r) { if(l > r) swap(l, r); int lb = l / B, rb = r / B, ans, CNT = 0; memset(c, 0, sizeof c); if(rb - lb > 1) { pii &t = Mode[lb + 1][rb - 1]; ans = t.first; CNT = t.second; for(int i = l; i / B == lb; i++) { int v = seq[i], Cnt = getCnt(lb, l % B, B - 1, v) + getCnt(rb, 0, r % B, v); Cnt += getSum(lb + 1, rb - 1, v); if(Cnt > CNT) ans = v, CNT = Cnt; else if(Cnt == CNT) ans = min(ans, v); } for(int i = rb * B; i <= r; i++) { int v = seq[i], Cnt = getCnt(lb, l % B, B - 1, v) + getCnt(rb, 0, r % B, v); Cnt += getSum(lb + 1, rb - 1, v); if(Cnt > CNT) ans = v, CNT = Cnt; else if(Cnt == CNT) ans = min(ans, v); } } else if(lb + 1 == rb) { for(int i = l; i / B == lb; i++) { int v = seq[i], Cnt = getCnt(lb, l % B, B - 1, v) + getCnt(rb, 0, r % B, v); if(Cnt > CNT) ans = v, CNT = Cnt; else if(Cnt == CNT) ans = min(ans, v); } for(int i = rb * B; i <= r; i++) { int v = seq[i], Cnt = getCnt(lb, l % B, B - 1, v) + getCnt(rb, 0, r % B, v); if(Cnt > CNT) ans = v, CNT = Cnt; else if(Cnt == CNT) ans = min(ans, v); } } else if(lb == rb) { for(; l <= r; l++) { int v = seq[l], Cnt = getCnt(lb, l % B, r % B, v); if(Cnt > CNT) ans = v, CNT = Cnt; else if(Cnt == CNT) ans = min(ans, v); } } return H._Hash(ans);} void Work() { int ans = 0; while(Q--) { int l = read(), r = read(); printf("%d\n", ans = solve((l + ans - 1) % N, (r + ans - 1) % N)); }} int main() { Init(); Work(); return 0;}-------------------------------------------------------------------

2724: [Violet 6]蒲公英

Time Limit: 40 Sec Memory Limit: 512 MB
Submit: 1140 Solved: 373
[Submit][Status][Discuss]

Description



Input



修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

Output



Sample Input

6 3
1 2 3 2 1 2
1 5
3 6
1 5

Sample Output

1
2
1

HINT



修正下:

n <= 40000, m <= 50000

Source

Vani原创
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: