Codeforces 1375 H : Set Merging
Posted weiyanpeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1375 H : Set Merging相关的知识,希望对你有一定的参考价值。
做了一天 Global 9 做吐了,全是构造属实有毒啊。
考虑在低于 (n^3) 的复杂度做出来这个东西:
考虑求所有区间。我们可以将其拆成值域 ([1, ext{mid}]) 和 ([ ext{mid}+1, r]) 两个序列,然后对每个区间将小于等于 (mid) 和大于 (mid) 的部分合并起来。
这样的次数是: (f(n) = 2*f(frac{n}{2})+ frac{n^2}{2}) 。可以分析出来,这个东西实际上是 (n^2) 次的。
然而直接 (n^2) 并不能通过,剩下的也很简单:考虑询问不多,我们将序列按值的大小拆成 (t) 个序列,每次 (t) 次合并完成一个询问。
(t) 取 (16) 即可。次数大概是: ((frac{4096}{16})^2*16+65536*16 = 2097152) 次。就过了。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int cnt;
const int N = (1<<12)+20;
vector < vector<int> > Block[17];
vector < pair<int,int> > operators;
inline int merge(int a,int b){
if(!a||!b)return a|b;
operators.push_back(make_pair(a,b));
return ++cnt;
}
int Limit;
int num;
int bel[N];
int a[N];
inline vector< vector<int> > get_idx(vector<int> idx, int all_rngs){
int n = idx.size()-1;
if(all_rngs==Limit){
++num; for(int i=1;i<=n;i++)bel[idx[i]] = num;
}
if(all_rngs<Limit){
vector<int> b;for(int i=1;i<=n;i++)b.push_back(a[idx[i]]);
sort(b.begin(),b.end());
int Split_Number=b[n/2-1];
vector<int> Lft(1,0), Rgt(1,0);
for(int i=1;i<=n;i++)
if(a[idx[i]]<=Split_Number)Lft.push_back(idx[i]);
else Rgt.push_back(idx[i]);
vector < vector<int> > L = get_idx(Lft, all_rngs*2);
vector < vector<int> > R = get_idx(Rgt, all_rngs*2);
return vector< vector<int> >();
}
vector< vector<int> > ret(n+2, vector<int>(n+2));
if(n==1){ret[1][1]=idx[1];}
else{
vector<int> b;for(int i=1;i<=n;i++)b.push_back(a[idx[i]]);
sort(b.begin(),b.end());
int Split_Number=b[n/2-1];
vector<int> Lft(1,0), Rgt(1,0);
for(int i=1;i<=n;i++)
if(a[idx[i]]<=Split_Number)Lft.push_back(idx[i]);
else Rgt.push_back(idx[i]);
vector < vector<int> > L = get_idx(Lft, all_rngs*2);
vector < vector<int> > R = get_idx(Rgt, all_rngs*2);
vector<int> pref[2];pref[0]=pref[1]=vector<int>(n+1,0);
for(int i=1;i<=n;i++){
pref[0][i]=pref[0][i-1], pref[1][i]=pref[1][i-1];
if(a[idx[i]]<=Split_Number)pref[0][i]++;
else pref[1][i]++;
}
for(int i=1;i<=n;i++)for(int j=i;j<=n;j++){
if(i==j)ret[i][j]=idx[i];
else{
ret[i][j]=merge(L[pref[0][i-1]+1][pref[0][j]],R[pref[1][i-1]+1][pref[1][j]]);
}
}
}
if(all_rngs==Limit){Block[num]=ret;}
return ret;
}
int pref[17][N];
int main()
{
cin >> n >> m;cnt=n;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
Limit=1;while(Limit*2<=n&&Limit<16)Limit<<=1;
vector<int> q(1,0);
for(int i=1;i<=n;i++)q.push_back(i);
get_idx(q,1);
for(int i=1;i<=n;i++){
for(int j=1;j<=num;j++)pref[j][i]=pref[j][i-1];
pref[bel[i]][i]++;
}
vector<int> ans;
while(m--){
int l,r;scanf("%d%d",&l,&r);
int cur=0;
for(int i=1;i<=num;i++){
int _l=pref[i][l-1]+1, _r=pref[i][r];
cur=merge(cur,Block[i][_l][_r]);
}
ans.push_back(cur);
}
cout << cnt << endl;
for(size_t i=0;i<operators.size();i++){
printf("%d %d
", operators[i].first, operators[i].second);
}
for(size_t i=0;i<ans.size();i++)printf("%d ", ans[i]);puts("");
return 0;
}
以上是关于Codeforces 1375 H : Set Merging的主要内容,如果未能解决你的问题,请参考以下文章
codeforces 675D Tree Construction set
codeforces #296 div2 (527C) STL中set的运用
Codeforces Round #580 (Div. 2)