zoukankan      html  css  js  c++  java
  • SPOJ 3267 DQUERY

    题目大意

    对于一个数列 (left{a_n ight}) , 有 (q) 次询问,第 (i) 次询问格式为 (l_i,r_i) , 求 (a_{l_i},a_{l_i + 1},a_{l_i + 2},dots,a_{r_i}) 中有多少不同的数。
    其中, (1 leq n leq 3 imes 10^4)(1 leq q leq 2 imes 10^5)(1 leq a_i leq 10^6)

    题解

    (n) 棵主席树,第 (i) 棵主席树记录前 (i) 个位置的状态。
    在进行 Insert 操作时,如果 (a_i) 在位置 (j) 出现过,那么位置 (i) 赋值为 (1) ,位置 (j) 赋值为 (0)
    即每次查询的答案为第 (r_i) 棵主席树中 ([l_i,r_i]) 的和。

    #include <cstdio>
    #include <algorithm>
    
    #define MAX_N (30000 + 5)
    #define MAX_A (1000000 + 5)
    #define MAX_SIZE 1020000
    
    using std::sort;
    
    struct Tree
    {
    	int size;
    	int l, r;
    };
    
    int n, q;
    int a[MAX_N];
    int h[MAX_A], nxt[MAX_N];
    int root[MAX_N], num;
    Tree s[MAX_SIZE];
    
    void Insert(int, int, int, int, int, int);
    int Query(int, int, int, int, int);
    
    int main()
    {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &a[i]);
    		nxt[i] = h[a[i]];
    		h[a[i]] = i;
    	}
    	for (int i = 1; i <= n; ++i)
    	{
    		root[i] = ++num;
    		Insert(root[i - 1], root[i], 1, n, nxt[i], i);
    	}
    	scanf("%d", &q);
    	int l, r;
    	while (q--)
    	{
    		scanf("%d%d", &l, &r);
    		printf("%d
    ", Query(root[r], 1, n, l, r)); 
    	}
    }
    
    void Insert(int r1, int r2, int L, int R, int p1, int p2)
    {
    	if (L == R)
    	{
    		if (L == p1) s[r2].size = 0;
    		else s[r2].size = 1;
    		return;
    	}
    	int mid = L + R >> 1;
    	s[r2].l = s[r1].l;
    	s[r2].r = s[r1].r;
    	if (L <= p1 && p1 <= mid || L <= p2 && p2 <= mid)
    	{
    		s[r2].l = ++num;
    		Insert(s[r1].l, s[r2].l, L, mid, p1, p2);
    	}
    	if (mid + 1 <= p1 && p1 <= R || mid + 1 <= p2 && p2 <= R)
    	{
    		s[r2].r = ++num;
    		Insert(s[r1].r, s[r2].r, mid + 1, R, p1, p2);
    	}
    	s[r2].size = s[s[r2].l].size + s[s[r2].r].size;
    }
    
    int Query(int idx, int L, int R, int lt, int rt)
    {
    	if (R < lt || rt < L) return 0;
    	if (lt <= L && R <= rt) return s[idx].size;
    	int mid = L + R >> 1;
    	return Query(s[idx].l, L, mid, lt, rt) + Query(s[idx].r, mid + 1, R, lt, rt); 
    }
    
  • 相关阅读:
    VMware安装最新版CentOS7图文教程
    git 本地给远程仓库创建分支 三步法
    git如何利用分支进行多人开发
    题解 洛谷P6478 [NOI Online #2 提高组] 游戏
    题解 CF1146D Frog Jumping
    题解 洛谷P6477 [NOI Online #2 提高组] 子序列问题
    题解 LOJ2472 「九省联考 2018」IIIDX
    题解 CF1340 A,B,C Codeforces Round #637 (Div. 1)
    题解 LOJ3284 「USACO 2020 US Open Platinum」Exercise
    windows上的路由表
  • 原文地址:https://www.cnblogs.com/kcn999/p/13437508.html
Copyright © 2011-2022 走看看