#1513 : 小Hi的烦恼
https://hihocoder.com/problemset/problem/1513
分析:
bitset,五维数点问题。
记录每一科的第i名前面有那些人,最后&起来就行了。
代码;
复杂度$O(k n^2/64)$,k为维数。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #include<bitset> 12 #define fi(s) freopen(s,"r",stdin); 13 #define fo(s) freopen(s,"w",stdout); 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 30001; 23 bitset<N> f[5][N], tmp; 24 int rnk[N][5], ord[N]; 25 // rnk[i][j] 第i人的第j科的排名。 ord[i] 当前这一科中,排名为i的是谁。 26 int main() { 27 int n = read(); 28 for (int i=1; i<=n; ++i) 29 for (int j=0; j<5; ++j) rnk[i][j] = read(); 30 for (int j=0; j<5; ++j) { 31 for (int i=1; i<=n; ++i) ord[rnk[i][j]] = i - 1; 32 for (int i=1; i<=n; ++i) { 33 f[j][i] = f[j][i - 1]; 34 f[j][i].set(ord[i]); 35 } 36 } 37 for (int i=1; i<=n; ++i) { 38 tmp.set(); 39 for (int j=0; j<5; ++j) tmp &= f[j][rnk[i][j] - 1]; 40 printf("%d\n",tmp.count()); 41 } 42 return 0; 43 }
分块打表,$O(k n \sqrt n / 64)$
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #include<bitset> 12 #define fi(s) freopen(s,"r",stdin); 13 #define fo(s) freopen(s,"w",stdout); 14 using namespace std; 15 typedef long long LL; 16 17 inline int read() { 18 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 19 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 20 } 21 22 const int N = 30001; 23 bitset<N> f[5][175], g[5], tmp; 24 int rnk[N][5], ord[5][N], bel[N], pos[N]; 25 26 void add(int j,int l,int r) { 27 for (int i=l; i<=r; ++i) g[j].set(ord[j][i]); 28 } 29 30 int main() { 31 int n = read(); 32 for (int i=1; i<=n; ++i) 33 for (int j=0; j<5; ++j) 34 rnk[i][j] = read(), ord[j][rnk[i][j]] = i - 1; 35 36 int B = sqrt(n); 37 for (int j=0; j<5; ++j) { 38 int p = 1; 39 for (int i=1; i<=n; i+=B,++p) 40 for (int k=1; k<=i; ++k) f[j][p].set(ord[j][k]); 41 } 42 for (int x,i=1; i<=n; ++i) { 43 if ((i - 1) % B == 0) x = (i - 1) / B + 1, pos[x] = i; 44 bel[i] = x; 45 } 46 for (int i=1; i<=n; ++i) { 47 tmp.set(); 48 for (int j=0; j<5; ++j) { 49 int t = rnk[i][j] - 1; 50 g[j] = f[j][bel[t]]; 51 if (pos[bel[t]] < t) add(j, pos[bel[t]] + 1, t); 52 tmp &= g[j]; 53 } 54 printf("%d\n",tmp.count()); 55 } 56 return 0; 57 }