zoukankan      html  css  js  c++  java
  • SPOJ3267--D-query (树状数组离线操作)

    题意查询区间 [l,r]内有多少个不同的数字

    先把所有询问按 右端点进行排序,然后离线操作。如果该位置的数字 已经出现过那么把前一个位置-1,当前位置+1。扫一遍输出。

     1 #include <cstdio>
     2 #include <string>
     3 #include <vector>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <algorithm>
     7 using namespace std;
     8 
     9 const int maxq = 2e5+10;
    10 const int maxn = 3e4+10;
    11 int last[1000050];
    12 int n,m,c[maxn],ans[200005];
    13 struct Node
    14 {
    15     int l,r,ans,idx;
    16     bool operator < (const Node &rhs)const
    17     {
    18         return r < rhs.r || (r == rhs.r && l < rhs.l);
    19     }
    20 }Q[maxq];
    21 int lowbit(int x)
    22 {
    23     return x & -x;
    24 }
    25 void add(int x,int d)
    26 {
    27     while (x <= maxn)
    28     {
    29         c[x] += d;
    30         x += lowbit(x);
    31     }
    32 }
    33 int sum(int x)
    34 {
    35     int ans = 0;
    36     while (x)
    37     {
    38         ans += c[x];
    39         x -= lowbit(x);
    40     }
    41     return ans;
    42 }
    43 int a[maxq];
    44 int main(void)
    45 {
    46     #ifndef ONLINE_JUDGE
    47         freopen("in.txt","r",stdin);
    48     #endif
    49     while (~scanf ("%d",&n))
    50     {
    51         memset(c,0,sizeof(c));
    52         memset(last,-1,sizeof(last));
    53         for (int i = 2; i <= n+1; i++)
    54             scanf ("%d",a+i);
    55         scanf ("%d",&m);
    56         for (int i = 0; i < m; i++)
    57         {
    58             Q[i].idx = i;
    59             scanf ("%d%d",&Q[i].l,&Q[i].r);
    60             Q[i].l++,Q[i].r++;
    61         }
    62         sort(Q,Q+m);
    63         int pre = 2;
    64         for (int i = 0; i < m; i++)
    65         {
    66             for(int j =  pre; j <= Q[i].r; j++)
    67             {
    68                 if (~last[a[j]])
    69                 {
    70                     add(last[a[j]],-1);
    71                     add(j,1);
    72                 }
    73                 else
    74                 {
    75                     add(j,1);
    76                 }
    77                 last[a[j]] = j;
    78             }
    79             ans[Q[i].idx] = sum(Q[i].r) - sum(Q[i].l - 1);
    80             pre = Q[i].r+1;
    81         }
    82         for (int i = 0; i < m; i++)
    83             printf("%d
    ",ans[i]);
    84     }
    85     return 0;
    86 }

    此题主席树也可以做。

  • 相关阅读:
    《构建之法》第1.2.3章读后感以及《硅谷传奇》观后感
    算复利条件下等额还款金额
    统计实验数据
    单利计算与复利计算程序
    了解和熟悉操作系统
    0302思考并回答一些问题
    sae storage 使用uploadify插件进行文件批量上传
    PHP页面之间跳转方法总结
    js获取每个按键的ASCII值
    C#文件的拆分与合并操作示例
  • 原文地址:https://www.cnblogs.com/oneshot/p/4110415.html
Copyright © 2011-2022 走看看