HihoCoder#1513 : 小Hi的煩惱(五維數點 bitset 分塊)

自為風月馬前卒發表於2018-10-10

題意

題目連結

Sol

五位數點問題,寫個cdq分治套cdq分治套cdq分治套cdq分析就完了 可以用bitset搞

對於每一科開(n)個bitset,其中(b[i])表示的排名為(1 – i)的人是哪些

查詢的時候把每科的bitset &起來就行了

複雜度(kfrac{n^2}{32})

然後可以分塊加速一下

注意這裡在預處理有個關於勢能分析的操作:如果塊內元素較少的話,可以每次跑根號個,然後和前面的|起來,如果元素較多的話直接從1開始跑

複雜度:(kfrac{nsqrt(n)}{32})

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30001;
inline int read() {
    int x = 0, f = 1; char c = getchar();
    while (c < `0` || c > `9`) {if (c == `-`) f = -1; c = getchar();}
    while (c >= `0` && c <= `9`) x = x * 10 + c - `0`, c = getchar();
    return x * f;
}
int N, a[5][MAXN], rak[5][MAXN], base = 1;
bitset<MAXN> B[5][175];
main() {
    N = read(); base = sqrt(N);
    for (int i = 1; i <= N; i++) for (int j = 0; j < 5; j++) a[j][i] = read(), rak[j][a[j][i]] = i;
    for (int j = 0; j < 5; j++) 
        for (int i = 1; i * base <= N; i++) 
            for(int k = 1; k <= i * base; k++) B[j][i].set(rak[j][k]);  
    for (int i = 1; i <= N; i++) {
        bitset<MAXN> tmp, cal; tmp.set();
        for(int j = 0; j < 5; j++) {
            cal.reset();
            int now = a[j][i] / base;
            cal |= B[j][now];
            for(int k = now * base + 1; k <= a[j][i]; k++) cal.set(rak[j][k]); 
            tmp &= cal;
        }
        printf("%d
", tmp.count() - 1);
    }
}  

相關文章