• 洛谷P1972 HH的项链【树状数组】


    题目https://www.luogu.org/problemnew/show/P1972

    题意:给定一个长度为n的序列,数字表示珠子的种类。m次查询每次询问给定区间内珠子的种类数。

    思路:可以说是运用了前缀和的思想吧。从前到后的去处理查询,而对于某一个查询区间,如果某一个种类出现了多次的话我们只需要计算最后一次出现。

    用query(x)表示1~x区间内的种类数,其中对每个种类我们只标记最后一次出现。也就是说顺序遍历的时候如果又出现了就把前面的清空,标记当前位置。

    如果查询的区间是l~r那么答案就是query(r) - query(l - 1)。

    所以首先需要把查询按照右端点从小到大排序。每次只需要更新上一次右端点到这一次右端点这一段区间,同时要标记每一个种类最近一次出现的位置,用于清空。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x3f3f3f3f
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int, int> pr;
    17 
    18 int n, m;
    19 const int maxn = 5e5 + 5;
    20 struct node{
    21     int l, r, id, ans;
    22 }q[maxn];
    23 int neck[maxn];
    24 int sum[maxn << 2];
    25 const int maxnum = 1e6 + 5;
    26 int pos[maxnum];
    27 
    28 bool cmp(node a, node b)
    29 {
    30     return a.r < b.r; 
    31 }
    32 
    33 bool cmp1(node a, node b)
    34 {
    35     return a.id < b.id;
    36 }
    37 
    38 
    39 void add(int rt, int val)
    40 {
    41     while(rt <= n){
    42         sum[rt] += val;
    43         rt += (rt & -rt);
    44     }
    45 }
    46 
    47 int query(int rt)
    48 {
    49     int ans = 0;
    50     while(rt){
    51         ans += sum[rt];
    52         rt -= (rt & -rt);
    53     }
    54     return ans;
    55 }
    56 
    57 int main()
    58 {
    59     scanf("%d", &n);
    60     for(int i = 1; i <= n; i++){
    61         scanf("%d", &neck[i]);
    62     }
    63     scanf("%d", &m);
    64     for(int i = 0; i < m; i++){
    65         scanf("%d%d", &q[i].l, &q[i].r);
    66         q[i].id = i;
    67     }
    68     sort(q, q + m, cmp);
    69     
    70     int nxt = 1;
    71     for(int i = 0; i < m; i++){
    72         int r = q[i].r;
    73         for(int j = nxt; j <= r; j++){
    74             if(pos[neck[j]]){
    75                 add(pos[neck[j]], -1);
    76             }
    77             add(j, 1);
    78             pos[neck[j]] = j;
    79         }
    80         nxt = r + 1;
    81         q[i].ans = query(q[i].r) - query(q[i].l - 1);
    82     }
    83     sort(q, q + m, cmp1);
    84     for(int i = 0; i < m; i++){
    85         printf("%d
    ", q[i].ans);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    基于开源SuperSocket实现客户端和服务端通信项目实战
    WinForm基于插件开发实现多项配置存储
    WinForm多线程实现HTTP网络检测工具
    .NET开源分布式日志框架ExceptionLess实战演练(公开版)
    让Windows Server 2008 + IIS 7+ ASP.NET 支持10万并发请求
    .NET基于Eleasticsearch搭建日志系统实战演练
    Spring-Bean配置-使用外部属性文件(转)
    spring事务的隔离级别(透彻理解)
    Spring事务传播机制与隔离级别(转)
    SQL语句200条(转)
  • 原文地址:https://www.cnblogs.com/wyboooo/p/11120884.html
Copyright © 2020-2023  润新知