zoukankan      html  css  js  c++  java
  • [SDOI2009] HH的项链 | 莫队模板

    题目链接:戳我

    题意:求区间中不同颜色的种类数

    因为是要过知识点,所以又把这题拿出来做了一遍。。。。。。这里就写两种方法吧

    主席树做法

    设pre[i]为第i个点上的颜色在前面序列中出现的最晚的一次的位置+1,那么就可以将问一个区间内有多少种颜色转化为——问一个区间内上有多少个点的pre在当前区间左端点之前。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 50010
    using namespace std;
    int n,m,cnt;
    int a[MAXN<<5],pre[MAXN<<5],last[MAXN<<5],rt[MAXN<<5];
    struct Node{int ls,rs,v;}t[MAXN<<5];
    inline void modify(int &x,int f,int l,int r,int pos,int k)
    {
        x=++cnt;
        t[x]=t[f];t[x].v+=k;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(pos<=mid) modify(t[x].ls,t[f].ls,l,mid,pos,k);
        else modify(t[x].rs,t[f].rs,mid+1,r,pos,k);
    }
    inline int query(int x,int f,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr) return t[x].v-t[f].v;
        int mid=(l+r)>>1;
        int cur_ans=0;
        if(ll<=mid) cur_ans+=query(t[x].ls,t[f].ls,l,mid,ll,rr);
        if(mid<rr) cur_ans+=query(t[x].rs,t[f].rs,mid+1,r,ll,rr);
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        freopen("ce.out","w",stdout);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&a[i]);
            pre[i]=last[a[i]]+1;
            last[a[i]]=i;
            modify(rt[i],rt[i-1],1,n,pre[i],1);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            printf("%d
    ",query(rt[v],rt[u-1],1,n,1,u));
        }
    }
    

    莫队做法

    莫队有些奇奇怪怪的块的大小,但是我不是特别会,所以就记成一般的根号的大小吧。
    然后排序的时候以所在块的编号为第一关键字,右端点为第二关键字。
    写的时候注意一下i++和++i的区别就可以了qwq

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define MAXN 1000100
    struct query{int l,r,t,id;}q[MAXN];
    int color[MAXN],A[MAXN],Ans,c[MAXN],n,m;
    bool operator <(query a,query b)
    {
        if(a.t==b.t)return a.r<b.r;
        return a.t<b.t;
    }
    inline void Change(int pos,int k)
    {
          color[c[pos]]+=k;
          if(color[c[pos]]==0&&k==-1)--Ans;
          if(color[c[pos]]==1&&k==+1)++Ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        int Len=sqrt(n);
        for(int i=1;i<=n;++i)scanf("%d",&c[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;++i)
            scanf("%d%d",&q[i].l,&q[i].r),q[i].t=(q[i].l-1)/Len+1,q[i].id=i;
        sort(&q[1],&q[m+1]);
        int l=1,r=0;
        for(int i=1;i<=m;++i)
        {
            while(l<q[i].l)Change(l,-1),l++;
            while(l>q[i].l)Change(l-1,1),l--;
            while(r<q[i].r)Change(r+1,1),r++;
            while(r>q[i].r)Change(r,-1),r--;
            A[q[i].id]=Ans;
        }
        for(int i=1;i<=m;++i)printf("%d
    ",A[i]);
        return 0;
    }
    

    BZOJ上如上代码 主席树2276ms,莫队1724ms qwqwq

  • 相关阅读:
    SGU 205. Quantization Problem
    BZOJ1009: [HNOI2008]GT考试
    SGU 204. Little Jumper
    Spring Aspect 获取请求参数
    springboot 是用拦截器Interceptor获取请求的控制器和请求的方法名
    spring boot Filter过滤器的简单使用
    Java 使用Query动态拼接SQl
    java 传入list集合 返回树形菜单,for循环遍历
    spring data jpa 的简单使用
    vue项目引入element
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10308954.html
Copyright © 2011-2022 走看看