zoukankan      html  css  js  c++  java
  • SPOJ D-query 【主席树】

    一 题目

      D-query

    二 分析

      主席树的运用。

      这题首先应该考虑的是,如何分出种类数?再就是考虑如何维护区间信息?

      最开始想的是直接离散化后用权值线段树建主席树,发现不行,因为假如$ [l,r] $的值在$l$之前已经出现了,那么直接用历史版本的相减肯定会出问题。所以排除此方法。

      所以在维护历史版本的时候要同时更新各个种类值的最新位置。这样就保证了,在给定$[l,r]$后就可以根据$r$位置的权值线段树,找到比$l$大的数目就是答案。

    三 AC代码

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int MAXN = 3e4 + 15;
     6 int n, q, a[MAXN], root[MAXN], tot;
     7 struct Node
     8 {
     9     int l, r, c;
    10 }T[MAXN*30];
    11 
    12 void build(int &rt, int l, int r)
    13 {
    14     T[++tot].c = 0;
    15     rt = tot;
    16     if(l == r)  return;
    17     int mid = (l+r)>>1;
    18     build(T[rt].l, l, mid);
    19     build(T[rt].r, mid + 1, r);
    20 }
    21 void update(int &cur, int pre,int l, int r, int pos, int val)
    22 {
    23     T[++tot] = T[pre];
    24     cur = tot;
    25     T[cur].c += val;
    26     if(l == r)  return;
    27     int m = (l + r) >> 1;
    28     if(pos <= m)
    29         update(T[cur].l, T[pre].l, l, m, pos, val);
    30     else
    31         update(T[cur].r, T[pre].r, m + 1, r, pos, val);
    32 }
    33 int query(int rt, int l, int r, int pos)
    34 {
    35     
    36     if(l >= pos)  return T[rt].c;
    37     int ans = 0;
    38     int m = (l + r) >>1;
    39     if(pos <= m)
    40     {
    41         ans += T[T[rt].r].c;
    42         ans += query(T[rt].l, l, m, pos);
    43     }
    44     else
    45     {
    46         ans += query(T[rt].r, m + 1, r, pos);
    47     }
    48     return ans;
    49 }
    50 int main()
    51 {
    52     //freopen("in.txt", "r", stdin);
    53     scanf("%d", &n);
    54     for(int i = 1; i <= n; i++)
    55     {
    56         scanf("%d", &a[i]);
    57     }
    58     tot = 0;
    59     build(root[0], 1, n);
    60     map<int, int> mp;
    61     for(int i = 1; i <= n; i++)
    62     {
    63         if(mp.find(a[i]) == mp.end())
    64             update(root[i], root[i-1], 1, n, i, 1);
    65         else
    66         {
    67             int tmp;
    68             update(tmp, root[i-1], 1, n, mp[a[i]], -1);
    69             update(root[i], tmp, 1, n, i, 1);
    70         }
    71         mp[a[i]] = i;
    72     }
    73     scanf("%d", &q);
    74     for(int i = 0; i < q; i++)
    75     {
    76         int x, y;
    77         scanf("%d%d", &x, &y);
    78         printf("%d
    ", query(root[y], 1, n, x));
    79     }
    80     return 0;
    81 }


     

  • 相关阅读:
    Guid ToString 格式
    SQL Server 自增字段归零
    一些被触动的话
    【简易教程】在网站上养一只萌咔咔的小仓鼠
    SQL分页语句
    WPF使用System.Windows.SystemParameters类获得屏幕分辨率
    WPF编程学习——窗口
    C# .net WPF无边框移动窗体
    WPF 4 Ribbon 开发 之 快捷工具栏(Quick Access Toolbar)
    转 遗传算法简介
  • 原文地址:https://www.cnblogs.com/dybala21/p/10852455.html
Copyright © 2011-2022 走看看