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

P1375 小猫(二飞的小憨猫)

codeforces #296 div2 (527C) STL中set的运用

Codeforces Round #580 (Div. 2)

Codeforces Round #658 (Div. 2)ABC2

Codeforces Round #386 (Div. 2) E - Numbers Exchange