zoukankan      html  css  js  c++  java
  • [CF1375H] Set Merging

    [题目链接]

    http://codeforces.com/contest/1375/problem/H

    [题解]

    考虑对值域分块。

    不难发现对于一段值域在 ([l , r]) 中对应的也是一段连续区间。

    那么不妨对每一段记 (f_{l , r}) 表示 ([l , r]) 这段区间对应的节点。

    考虑建出一个类似于线段树的结构进行分治 , 每次递归处理小于 / 大于 (mid) 的数形成的集合。最后对跨过 (mid) 的进行合并即可。

    这样做的复杂度 (T(B) = 2T(frac{B}{2}) + B ^ 2 approx O(B ^ 2))

    一共有 (frac{N}{B}) 个块 , 故这部分复杂度 (O(NB))

    那么对于每个需求只需将其对应的每块值域的节点合并起来即可。

    (B)(sqrt{N}) 时 , 操作数约为 (Nsqrt{N} approx 2.2 * 10 ^ {6})

    [代码]

    #include<bits/stdc++.h>
     
    using namespace std;
     
    typedef long long LL;
     
    #define rep(i , l , r) for (int i = (l); i < (r); ++i)
     
    typedef pair < int , int > pii;
    #define mp make_pair
     
    const int MN = 1e5 , MM = 2e6 , MS = 2.5e6 + 5 , MB = 1 << 8;
     
    int A[MN] , rv[MN];
    int N , M , siz , ans[MN] , B;
    vector < pii > way;
     
    inline int merge(int u , int v) {
    	if (!u || !v) return u + v;
    	way.emplace_back(mp(u , v));
    	return ++siz;
    }
     
    int f[MB * 2 + 5][MB + 5][MB + 5];
     
    struct Block {
    	int l , r;
    	inline void solve(int u , int l , int r , vector < int > V) {
    		if (l == r) { f[u][1][1] = rv[V[1]]; return; }
    		int mid = l + r >> 1; vector < int > LV(1) , RV(1);
    		for (int i = 1; i < V.size(); ++i) 
    			 if (V[i] <= mid) LV.emplace_back(V[i]);
    			 else RV.emplace_back(V[i]);
    		solve(u << 1 , l , mid , LV); solve(u << 1 | 1 , mid + 1 , r , RV);
    		for (int i = 1 , xl = 1 , xr = 1; i < V.size(); xl += (V[i] <= mid) , xr += (V[i] > mid) , ++i) {
    			for (int j = i - 1 , yl = xl - 1 , yr = xr - 1; j < V.size(); ++j , yl += (V[j] <= mid) , yr += (V[j] > mid)) {
    				if (j == i - 1) continue;
    				f[u][i][j] = merge(f[u << 1][xl][yl] , f[u << 1 | 1][xr][yr]);
    			}
    		}
    	}
    	int home[MN] , res[MB + 5][MB + 5];
    	inline void build() {
    		vector < int > vec(1);
    		for (int i = 1; i <= N; ++i) 
    			if (A[i] >= l && A[i] <= r) {
    				vec.emplace_back(A[i]);
    				home[i] = home[i - 1] + 1;
    			} else home[i] = home[i - 1];
    		solve(1 , l , r , vec);
    		for (int i = 1; i < vec.size(); ++i)
    		for (int j = 1; j < vec.size(); ++j)
    			res[i][j] = f[1][i][j];
    		return;
    	}
    	inline int query(int l , int r) {
    		return res[home[l - 1] + 1][home[r]];
    	}
    } blo[20];
     
    int main() {
    	 
    	 scanf("%d%d" , &N , &M); siz = N , B = min(N , MB);
    	 for (int i = 1; i <= N; ++i) {
    	 	 scanf("%d" , &A[i]);
    	 	 rv[A[i]] = i;
    	 }
    	 for (int i = 1; (i - 1) * B + 1 <= N; ++i) {
    	 	 blo[i].l = (i - 1) * B + 1 , blo[i].r = i * B;
    		 blo[i].build(); 
    	 }
    	 for (int i = 1; i <= M; ++i) {
    	 	 int l , r; scanf("%d%d" , &l , &r); ans[i] = 0;
    	 	 for (int j = 1; j <= (N - 1) / B + 1; ++j)
    	 	 	ans[i] = merge(ans[i] , blo[j].query(l , r));
    	 }
    	 printf("%d
    " , siz);
    	 for (auto x : way)
    	  	 printf("%d %d
    " , x.first , x.second);
    	 for (int i = 1; i <= M; ++i)
    	 	 printf("%d " , ans[i]);
    	 printf("
    ");
         return 0;
    }
    
  • 相关阅读:
    javascript:属性的操作
    javascript:Element 节点
    javascript:ParentNode 接口,ChildNode 接口
    javascript:NodeList 接口,HTMLCollection 接口
    javascript:Node接口
    javascript:DOM概述
    javascript:Promise 对象
    javascript:定时器
    javascript:异步操作概述
    javascript:严格模式
  • 原文地址:https://www.cnblogs.com/evenbao/p/14441479.html
Copyright © 2011-2022 走看看