2 条题解

  • 0
    @ 2025-10-8 17:06:59

    C92 树状数组+排序 P4113 [HEOI2012] 采花

    // 树状数组+排序 O(nlogn)
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    #define N 2000010
    #define lowb(x) x&-x
    int n,c,m,a[N],pos1[N],pos2[N],ans[N];
    int s[N]; //区间内1的个数
    struct Q{
      int l,r,id; //查询的区间端点,查询的编号
      bool operator<(const Q& b)const{return r<b.r;}
    }q[N];
    
    void change(int x,int k){ //向后修
      while(x<=n) s[x]+=k, x+=lowb(x);
    }
    int query(int x){ //向前查
    int t=0;
      while(x) t+=s[x], x-=lowb(x);
      return t;
    }
    int main(){
      scanf("%d%d%d",&n,&c,&m);
      for(int i=1;i<=n;++i)scanf("%d",&a[i]);
      for(int i=1;i<=m;++i)
        scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
      sort(q+1,q+m+1); //查询按右端点排序
      
      for(int i=1,j=1;i<=m;++i){     //枚举每个查询
        for(;j<=q[i].r;++j){         //枚举r前面的位置
          if(!pos1[a[j]])            //若aj第1次位置为空
            pos1[a[j]]=j;            //记录aj第1次出现位置
          else{                      //若aj第1次位置不空
            if(!pos2[a[j]]){         //若aj第2次位置为空
              change(pos1[a[j]],1);  //aj第1次出现位置+1
              pos2[a[j]]=j;          //记录aj第2次出现位置
            }
            else{                    //若aj第2次位置不空
              change(pos1[a[j]],-1); //aj第1次出现位置清空
              change(pos2[a[j]],1);  //aj第2次出现位置+1
              pos1[a[j]]=pos2[a[j]]; //第2次位置变成第1次
              pos2[a[j]]=j;          //当前位置变成第2次
            }
          }
        }
        ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
      }
      for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
    }
    
    • 0
      @ 2025-10-8 17:06:46

      C92 树状数组+排序 P4113 [HEOI2012] 采花

      // 树状数组+排序 O(nlogn)
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      using namespace std;
      
      #define N 2000010
      #define lowb(x) x&-x
      int n,c,m,a[N],pos1[N],pos2[N],ans[N];
      int s[N]; //区间内1的个数
      struct Q{
        int l,r,id; //查询的区间端点,查询的编号
        bool operator<(const Q& b)const{return r<b.r;}
      }q[N];
      
      void change(int x,int k){ //向后修
        while(x<=n) s[x]+=k, x+=lowb(x);
      }
      int query(int x){ //向前查
        int t=0;
        while(x) t+=s[x], x-=lowb(x);
        return t;
      }
      int main(){
        scanf("%d%d%d",&n,&c,&m);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        for(int i=1;i<=m;++i)
          scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
        sort(q+1,q+m+1); //查询按右端点排序
        
        for(int i=1,j=1;i<=m;++i){     //枚举每个查询
          for(;j<=q[i].r;++j){         //枚举r前面的位置
            if(!pos1[a[j]])            //若aj第1次位置为空
              pos1[a[j]]=j;            //记录aj第1次出现位置
            else{                      //若aj第1次位置不空
              if(!pos2[a[j]]){         //若aj第2次位置为空
                change(pos1[a[j]],1);  //aj第1次出现位置+1
                pos2[a[j]]=j;          //记录aj第2次出现位置
              }
              else{                    //若aj第2次位置不空
                change(pos1[a[j]],-1); //aj第1次出现位置清空
                change(pos2[a[j]],1);  //aj第2次出现位置+1
                pos1[a[j]]=pos2[a[j]]; //第2次位置变成第1次
                pos2[a[j]]=j;          //当前位置变成第2次
              }
            }
          }
          ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
        }
        for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
      }
      • 1

      C92 树状数组+排序 [HEOI2012] 采花

      信息

      ID
      4408
      时间
      1000ms
      内存
      512MiB
      难度
      10
      标签
      递交数
      2
      已通过
      2
      上传者