• [SDOI2009]HH的项链


    OJ题号:BZOJ1878、洛谷1972

    思路:树状数组离线化。

    不难想到,对于一个[l,r]的区间,如果出现了多个相同的颜色,我们可以只关心在区间[l,r]中,该颜色最后一个贝壳。

    例如,对于形如{1,2,3,2,1}的项链,当我们询问区间[1,5]时,该项链等同于{0,0,3,2,1}(方便起见,这里用0表示空)。

    于是就有了以下的思路:当询问[l,r]时,答案即为区间[l,r]内新出现的贝壳的个数。

    显而易见,当新的贝壳出现时,原来的同色贝壳都会失效。

    那么问题来了,对于{1,2,3,2,1}这个项链,当我们询问[1,5]时,答案是3;当我们询问[1,3]时,答案也是3,但如果使用上面的方法,我们记录的是{0,0,3,2,1},输出的答案是1。怎么办?

    一种思路是使用可持久化数据结构,比如主席树(可持久化线段树)等。然而当时主席树似乎并没有被发明?

    这里介绍一种离散化做法。

    首先对所有的询问预处理,即以右端点r为关键字进行排序。

    建立一个树状数组,记录每个前缀新出现的贝壳的个数。

    当然树状数组并不能一次性建好,每次根据当前询问的r,加入位置≤r的所有贝壳(将树状数组中的位置标记为1),并删去相同颜色的贝壳(将树状数组中的位置标记为0)。

    然后发现洛谷上能A,在BZOJ上就RE了?

     最后发现的原因:代表颜色的数字不一定是连续的,而且可能会很大(编号为0到1000000之间的整数),所以直接开数组会爆,解决的方法是Hash(不方便)或者Map。

    RunID User Problem Result Memory Time Language Code_Length Submit_Time
    2084658 skylee 1878 Accepted 4668 kb 1488 ms C++/Edit 1324 B 2017-05-27 17:34:54
     1 #include<map>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<utility>
     5 #include<algorithm>
     6 #define r first
     7 #define l second.first
     8 #define id second.second
     9 typedef std::pair<int,std::pair<int,int> > Q;
    10 const int N=50001;
    11 int n;
    12 class FenwickTree {
    13     private:
    14         int val[N];
    15         int lowbit(const int x) {
    16             return x&-x;
    17         }
    18     public:
    19         FenwickTree() {
    20             memset(val,0,sizeof val);
    21         }
    22         void modify(int p,const int x) {
    23             while(p<=n) {
    24                 val[p]+=x;
    25                 p+=lowbit(p);
    26             }
    27         }
    28         int query(int p) {
    29             int ans=0;
    30             while(p) {
    31                 ans+=val[p];
    32                 p-=lowbit(p);
    33             }
    34             return ans;
    35         }
    36 };
    37 FenwickTree tree;
    38 int main() {
    39     scanf("%d",&n);
    40     int a[n+1];
    41     for(int i=1;i<=n;i++) {
    42         scanf("%d",&a[i]);
    43     }
    44     int m;
    45     scanf("%d",&m);
    46     Q q[m];
    47     for(int i=0;i<m;i++) {
    48         scanf("%d%d",&q[i].l,&q[i].r);
    49         q[i].id=i;
    50     }
    51     std::sort(&q[0],&q[m]);
    52     int p=1;
    53     std::map<int,int> last;
    54     int ans[m];
    55     for(int i=0;i<m;i++) {
    56         while(p<=q[i].r) {
    57             if(last[a[p]]) tree.modify(last[a[p]],-1);
    58             tree.modify(last[a[p]]=p,1);
    59             p++;
    60         }
    61         ans[q[i].id]=tree.query(q[i].r)-tree.query(q[i].l-1);
    62     }
    63     for(int i=0;i<m;i++) printf("%d
    ",ans[i]);
    64     return 0;
    65 }
  • 相关阅读:
    C++-蓝桥杯-小数第n位[除法模拟]
    C++-蓝桥杯-合成植物[并查集][模板题]
    Overleaf操作
    三维向量差积,以及应用
    C++-蓝桥杯-分考场[2017真题][搜索][无向图染色]
    C++-POJ1094-Sorting It All Out[拓扑排序][邻接矩阵]
    C++-LUOGU1059-明明的随机数[堆排序]
    C++-快速排序[STL][快速排序][并归排序][堆排序]
    C++-蓝桥杯-波动数组[2014真题][DP优化]
    C++-蓝桥杯-[T1~T3][结果填空题][2015真题][水题]
  • 原文地址:https://www.cnblogs.com/skylee03/p/6913749.html
Copyright © 2020-2023  润新知