zoukankan      html  css  js  c++  java
  • 【题解】Luogu P4396 [AHOI2013]作业

    原题传送门

    最快的解法好像是cdq,但窝只会莫队+线段树/树状数组的做法

    题目要我们求1.在区间[l,r]中值域在[a,b]中有多少个数2.在区间[l,r]中值域在[a,b]中有多少个不同数

    一眼就看出莫队,再拿数据结构维护维护就行了,一看,3000ms,应该跑得过

    用线段树交了一发,发现完美的被卡(因为线段树单点修改的复杂度是严格的(O(log n))

    改成树状数组就跑得飞快(树状数组跑不满(O(log n))

    最后时间复杂度是(O(n sqrt n log n))

    #include <bits/stdc++.h>
    #define N 100005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    struct query{
        int l,r,a,b,id,bl;
    }q[N];
    inline bool cmp(register query a,register query b)
    {
        return a.bl!=b.bl?a.l<b.l:((a.bl&1)?a.r<b.r:a.r>b.r);
    }
    int n,m,v[N],blocksize=0; 
    int p[N],ans1[N],ans2[N];
    struct BinaryIndexTree{
        int tr[N];
        inline void update(register int pos,register int x)
        {
            for(register int i=pos;i<=n;i+=i&(-i))
                tr[i]+=x;
        }
        inline int query(register int pos)
        {
            int res=0;
            for(register int i=pos;i;i-=i&(-i))
                res+=tr[i];
            return res;
        }
    }tr1,tr2;
    inline void add(register int x)
    {
        if(++p[v[x]]==1)
            tr2.update(v[x],1);
        tr1.update(v[x],1);
    }
    inline void del(register int x)
    {
        if(--p[v[x]]==0)
            tr2.update(v[x],-1);
        tr1.update(v[x],-1);
    }
    int main()
    {
        n=read(),m=read();
        blocksize=(int)pow(n,0.58);;
        for(register int i=1;i<=n;++i)
            v[i]=read();
        for(register int i=1;i<=m;++i)
            q[i].l=read(),q[i].r=read(),q[i].a=read(),q[i].b=read(),q[i].id=i,q[i].bl=(q[i].l-1)/blocksize+1;
        sort(q+1,q+1+m,cmp);
        int l=1,r=0;
        for(register int i=1;i<=m;++i)
        {
            int ll=q[i].l,rr=q[i].r;
            while(l>ll)
                add(--l);
            while(r<rr)
                add(++r);
            while(l<ll)
                del(l++);
            while(r>rr)
                del(r--);
            ans1[q[i].id]=tr1.query(q[i].b)-tr1.query(q[i].a-1);
            ans2[q[i].id]=tr2.query(q[i].b)-tr2.query(q[i].a-1);
        }
        for(register int i=1;i<=m;++i)
            write(ans1[i]),putchar(' '),write(ans2[i]),puts("");
        return 0;
    }
    
  • 相关阅读:
    Shell编程------函数应用
    Shell编程------循环语句
    Shell编程------判断语句
    Shell编程------变量、赋值和运算
    Action实现prepareable接口后定义前置方法
    动态代理模式
    hibernate持久化对象,
    view视图总结
    servlet和Struts2的线程安全性对比
    Action获取请求参数的3中方式
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10350925.html
Copyright © 2011-2022 走看看