zoukankan      html  css  js  c++  java
  • HDU5654xiaoxin and his watermelon candy 离线+树状数组

    题意:bc 77div1 d题(中文题面),其实就是询问一个区间有多少不同的三元组,当然这个三元组要符合条件

    分析(先奉上官方题解)

    首先将数列中所有满足条件的三元组处理出来,数量不会超过 nn个。

    设 pre[i] 为第 i 个三元组前一次出现的位置,如果在前面没有出现过则设为0,对于不合法的三元组,pre[i]设为 n。

    这样对于一个查询 [L, R], 我们只不需要计算出 在这个区间内有多少个三元组的 pre 值是小于 L 的。

    到这里,就可以使用可持久化线段树来计算了。

    -------------------------------------------------------------华丽的分割线

    然后蒟蒻表示不会这种在线的主席树做法,主席树据说很好,马上去学习

    然后介绍本蒟蒻的离线做法,其实都是套路,就是求一个区间包含了,多少个小区间(即三元组)

    首先和题解一样,找到符合条件的三元组,记录它的序号id,这个三元组的每个元素,他的右边界

    然后按照三元组排序,以及他的id,这样处理每个三元组的pre,即在他左边,与他相同的三元组的id

    然后恢复下顺序

    然后就是离线的套路,把查询区间按照右端点排序,更新所有三元组右边界小于他的左端点,然后区间求和,就是答案

    但是这个题有一个点,要避免查询重复,所以在当前查询的时候,要保证没有重复,所以更新三元组时,要把他的pre删掉(因为相同)

    这样对于重复的三元组,只保留最靠近当前查询区间右端的

    代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    const int INF=0x3f3f3f3f;
    struct Node{
      int a,b,c,id,pre,r;
      bool operator==(const Node &rhs)const{
         if(a==rhs.a&&b==rhs.b&&c==rhs.c)
          return 1;
          return 0;
      }
    }o[N];
    int n,T,q;
    bool cmp1(Node x,Node y){
      if(x.a!=y.a)
        return x.a<y.a;
      if(x.b!=y.b)
        return x.b<y.b;
      if(x.c!=y.c)
        return x.c<y.c;
      return x.id<y.id;
    }
    bool cmp2(Node x,Node y){
      return x.id<y.id;
    }
    int d[N],ans[N];
    struct Q{
      int l,r,id;
      bool operator<(const Q &rhs)const{
         return r<rhs.r;
      }
    }p[N];
    int bit[N];
    void add(int x,int t){
      for(int i=x;i<=n;i+=i&(-i))
         bit[i]+=t;
    }
    int get(int x){
      int ans=0;
      for(int i=x;i>0;i-=i&(-i))
         ans+=bit[i];
      return ans;
    }
    int main(){ 
        scanf("%d",&T);
        while(T--){
          scanf("%d",&n);
          int cnt=0;
          for(int i=1;i<=n;++i){
            scanf("%d",&d[i]);
            if(i<=2)continue;
            if(d[i]>=d[i-1]&&d[i-1]>=d[i-2]){
               ++cnt;
               o[cnt].a=d[i-2],o[cnt].b=d[i-1];
               o[cnt].c=d[i],o[cnt].pre=-1;
               o[cnt].r=i,o[cnt].id=cnt;
            }
          }
          sort(o+1,o+1+cnt,cmp1);
          for(int i=2;i<=n;++i){
            if(o[i]==o[i-1]){
              o[i].pre=o[i-1].id;
            }
          }
          sort(o+1,o+1+cnt,cmp2);
          scanf("%d",&q);
          for(int i=1;i<=q;++i){
            scanf("%d%d",&p[i].l,&p[i].r);
            p[i].id=i;
          }
          sort(p+1,p+1+q);
          int pos=1;
          memset(bit,0,sizeof(bit));
          for(int i=1;i<=q;++i){
            for(;pos<=cnt&&o[pos].r<=p[i].r;++pos){
              int pre=o[pos].pre;
              if(pre!=-1)
                add(o[pre].r-2,-1);
              add(o[pos].r-2,1);
            }
            ans[p[i].id]=get(p[i].r)-get(p[i].l-1);
          }
          for(int i=1;i<=q;++i)
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python functools.lru_cache做备忘功能
    python clock装饰器 计算函数执行时间,执行结果及传入的参数
    python 闭包计算移动均值及nonlocal的使用
    使用 memoryview 和 struct 查看一个 GIF 图像的首部
    寻医问药 爬虫
    defaultdict使用及__missing__理解
    字典推导式
    collections deque队列及其他队列
    bisect 二分查找
    python array 使用创建10万浮点数
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5335094.html
Copyright © 2011-2022 走看看