zoukankan      html  css  js  c++  java
  • [HEOI2012]采花(树状数组)(暑假D11)

    题意

    求一段区间中出现至少2次的数的个数。

    保证n,m,c2106,c是值域

    题解

    上课讲的时候觉得有些熟悉,后来才想起来就是HH的项链的变式,觉得这思路还是值得记一下。

    第一种就是莫队做法,操作很简单,但是会超时。

    比较巧妙的思路就是,对于右端点相同的查询,如果一个数出现了至少两次,那么我们只关心他第二次出现的位置,因为如果包含他第3次或者更多次出现的位置,就一定包含他,而且只需两次就可以有贡献,多了贡献也不会增加。

    以序列位置为下标建立树状数组,对于从右往左出现第二次的数,在这个位置+1;

    对于同一个右端点的查询,就是查询区间和。

    当右端点移动时,这个数成为第一次出现的数;对于之前第一次出现的数就变成了第二次出现的数,对于该位置+1;之前第二次出现的数,这时他变成第三次出现已经没有任何贡献,这个位置-1;

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=2000005;
    int n,m,c;
    int pos[maxn],size;
    int co[maxn],fir[maxn],sec[maxn];
    int cx[maxn<<1];
    int ans[maxn];
    struct question{
        int l,r,id;
    }q[maxn];
    
    template<class T>inline void read(T &x){
        x=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    }
    
    bool cmp(question a,question b){return a.r<b.r;}
    
    void add(int x,int val){for(;x<=n;x+=x&-x) cx[x]+=val;}
    
    int query(int x){
        int ret=0;
        for(;x;x-=x&-x) ret+=cx[x];
        return ret;
    }
    
    int main(){
        read(n);read(c);read(m);
        for(int i=1;i<=n;i++) read(co[i]);
        for(int i=1;i<=m;i++){read(q[i].l);read(q[i].r);q[i].id=i;}
        sort(q+1,q+m+1,cmp);
        int j=1;
        for(int i=1;i<=n;i++){
            if(!fir[co[i]])//这个数之前没出现
             fir[co[i]]=i;
            else if(!sec[co[i]]){//只有一个 
               add(fir[co[i]],1);
               sec[co[i]]=fir[co[i]];
               fir[co[i]]=i;
            }
            else {//出现了两次以上 
              add(sec[co[i]],-1);
              add(fir[co[i]],1);
              sec[co[i]]=fir[co[i]];
              fir[co[i]]=i;
            }
            while(q[j].r==i) ans[q[j].id]=query(q[j].r)-query(q[j].l-1),j++;
        }
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    View Code
  • 相关阅读:
    java8新特性之Lambda表达式入门
    小结
    Kafka入门
    关于java多线程初试
    关于Netty入门
    IOS UITableView代码添加数据源和指定委托
    C#读书笔记1
    vs2008 C# Windows Mobile 智能设备开发 初步1
    Microsoft ActiveSync简介(来自网络)
    winForm单击用户区可移动窗体,代码控制窗体最大适中
  • 原文地址:https://www.cnblogs.com/sto324/p/11234613.html
Copyright © 2011-2022 走看看