zoukankan      html  css  js  c++  java
  • SPOJ DQUERY D-query (主席树)

    题意:给定上一个序列,然后有一些询问,问你区间 l - r 中有多少个不同的数。

    析:一个主席树入门题,首先是先进行处理,记录不同数出现的个数,如果相同的,先减去以前的,再加上这个最新的,

    对于查询,处理好,每一部分。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #define debug() puts("++++");
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define freopenr freopen("in.txt", "r", stdin)
    #define freopenw freopen("out.txt", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 0x3f3f3f3f3f3f;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 30000 + 10;
    const int maxm = maxn * 100;
    const int mod = 10;
    const int dr[] = {-1, 0, 1, 0};
    const int dc[] = {0, 1, 0, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    int a[maxn], T[maxn];
    int lch[maxm], rch[maxm], c[maxm];
    int tot;
    map<int, int> mp;
    
    int build(int l, int r){
      int rt = tot++;
      c[rt] = 0;
      if(l == r)  return rt;
      int m = l + r >> 1;
      lch[rt] = build(l, m);
      rch[rt] = build(m+1, r);
      return rt;
    }
    
    int update(int rt, int pos, int val){
      int newrt = tot++;
      int tmp = newrt;
      int l = 1, r = n;
      c[newrt] = c[rt] + val;
      while(l < r){
        int m = l + r >> 1;
        if(pos <= m){
          lch[newrt] = tot++;
          rch[newrt] = rch[rt];
          newrt = lch[newrt];
          rt = lch[rt];
          r = m;
        }
        else{
          rch[newrt] = tot++;
          lch[newrt] = lch[rt];
          newrt = rch[newrt];
          rt = rch[rt];
          l = m + 1;
        }
        c[newrt] = c[rt] + val;
      }
      return tmp;
    }
    
    int query(int rt, int pos){
      int l = 1, r = n;
      int ans = 0;
      while(pos < r){
        int m = l + r >> 1;
        if(pos <= m){
          rt = lch[rt];
          r = m;
        }
        else{
          l = m + 1;
          ans += c[lch[rt]];
          rt = rch[rt];
        }
      }
      return ans + c[rt];
    }
    
    int main(){
      while(scanf("%d", &n) == 1){
        for(int i = 1; i <= n; ++i)
          scanf("%d", a+i);
        mp.clear();
        tot = 0;
        T[n+1] = build(1, n);
        for(int i = n; i; --i){
          if(mp.count(a[i])){
            int tmp = update(T[i+1], mp[a[i]], -1);
            T[i] = update(tmp, i, 1);
          }
          else T[i] = update(T[i+1], i, 1);
          mp[a[i]] = i;
        }
        scanf("%d", &m);
        while(m--){
          int l, r;
          scanf("%d %d", &l, &r);
          printf("%d
    ", query(T[l], r));
        }
      }
      return 0;
    }
    

      

  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/7259540.html
Copyright © 2011-2022 走看看