您的位置:首页 > 其它

Hihocoder #1513 : 小Hi的烦恼

2018-10-09 14:29 295 查看

#1513 : 小Hi的烦恼

https://hihocoder.com/problemset/problem/1513

分析:

  bitset,五维数点问题。

  记录每一科的第i名前面有那些人,最后&起来就行了。

代码;

复杂度$O(k n^2/64)$,k为维数。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL;

inline int read() {
int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 30001;
bitset<N> f[5]
, tmp;
int rnk
[5], ord
;
// rnk[i][j] 第i人的第j科的排名。 ord[i] 当前这一科中,排名为i的是谁。
int main() {
int n = read();
for (int i=1; i<=n; ++i)
for (int j=0; j<5; ++j) rnk[i][j] = read();
for (int j=0; j<5; ++j) {
for (int i=1; i<=n; ++i) ord[rnk[i][j]] = i - 1;
for (int i=1; i<=n; ++i) {
f[j][i] = f[j][i - 1];
f[j][i].set(ord[i]);
}
}
for (int i=1; i<=n; ++i) {
tmp.set();
for (int j=0; j<5; ++j) tmp &= f[j][rnk[i][j] - 1];
printf("%d\n",tmp.count());
}
return 0;
}

 

分块打表,$O(k n \sqrt n / 64)$

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL;

inline int read() {
int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 30001;
bitset<N> f[5][175], g[5], tmp;
int rnk
[5], ord[5]
, bel
, pos
;

void add(int j,int l,int r) {
for (int i=l; i<=r; ++i) g[j].set(ord[j][i]);
}

int main() {
int n = read();
for (int i=1; i<=n; ++i)
for (int j=0; j<5; ++j)
rnk[i][j] = read(), ord[j][rnk[i][j]] = i - 1;

int B = sqrt(n);
for (int j=0; j<5; ++j) {
int p = 1;
for (int i=1; i<=n; i+=B,++p)
for (int k=1; k<=i; ++k) f[j]

.set(ord[j][k]); } for (int x,i=1; i<=n; ++i) { if ((i - 1) % B == 0) x = (i - 1) / B + 1, pos[x] = i; bel[i] = x; } for (int i=1; i<=n; ++i) { tmp.set(); for (int j=0; j<5; ++j) { int t = rnk[i][j] - 1; g[j] = f[j][bel[t]]; if (pos[bel[t]] < t) add(j, pos[bel[t]] + 1, t); tmp &= g[j]; } printf("%d\n",tmp.count()); } return 0; }

[p] 

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