zoukankan      html  css  js  c++  java
  • P4396 [AHOI2013]作业

    传送门

    设 $pre[i]$ 表示位置 $i$ 的数上一次出现时的位置,如果是第一次出现则 $pre[i]=0$

    对于每个询问的第二个部分,即是问在区间 $[l,r]$ ,权值 $[a,b]$ ,$pre<l$ 的数的数量

    对于第一个部分,就是问区间 $[l,r]$ ,权值 $[a,b]$ ,的数的数量

    显然就是三维数点,直接 $cdq$ 套上即可,实现细节还是看代码吧

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=5e6+7;
    int n,m,a[N],b[N],pre[N],ans1[N],ans2[N];
    struct dat {
        int x,y,z,id,p;
        dat (int _x=0,int _y=0,int _z=0,int _id=0,int _p=0) { x=_x,y=_y,z=_z,id=_id,p=_p; }
        inline bool operator < (const dat &tmp) const {
            if(x!=tmp.x) return x<tmp.x;
            if(y!=tmp.y) return y<tmp.y;
            return z!=tmp.z ? z<tmp.z : id<tmp.id;
        }
    }d[N],tmp[N];
    int t[N];
    inline void add(int x,int v) { while(x<=n) t[x]+=v,x+=x&-x; }
    inline int ask(int x) { int res=0; while(x) res+=t[x],x-=x&-x; return res; }
    inline bool fc(dat &A,dat &B) { return A.y!=B.y ? A.y<B.y : A.id<B.id; }
    inline void calc(int j) { ans2[d[j].id]+=d[j].p*ask(d[j].z+1); ans1[d[j].id]+=d[j].p*ask(n); }
    void solve(int l,int r)
    {
        if(l==r) return;
        int mid=l+r>>1,i=l,j=mid+1,tot=l-1;
        solve(l,mid); solve(mid+1,r);
        while(i<=mid&&j<=r)
        {
            if(fc(d[i],d[j]))
            {
                if(!d[i].id) add(d[i].z+1,1);
                tmp[++tot]=d[i++];
            }
            else { if(d[j].id) calc(j); tmp[++tot]=d[j++]; }
        }
        while(i<=mid) { if(!d[i].id) add(d[i].z+1,1); tmp[++tot]=d[i++]; }
        while(j<=r) { if(d[j].id) calc(j); tmp[++tot]=d[j++]; }
        for(int k=l;k<=mid;k++) if(!d[k].id) add(d[k].z+1,-1);
        for(int k=l;k<=r;k++) d[k]=tmp[k];
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++) b[i]=a[i]=read();
        sort(b+1,b+n+1); int tot=0,l,r,A,B;
        for(int i=1;i<=n;i++)
        {
            a[i]=lower_bound(b+1,b+n+1,a[i])-b;
            d[++tot]=dat(i,a[i],pre[a[i]],0,0);
            pre[a[i]]=i;
        }
        for(int i=1;i<=m;i++)
        {
            l=read(),r=read(),A=read(),B=read();
            A=lower_bound(b+1,b+n+1,A)-b;
            B=upper_bound(b+1,b+n+1,B)-b-1;
            d[++tot]=dat(l-1,A-1,l-1,i,1);
            d[++tot]=dat(r,B,l-1,i,1);
            d[++tot]=dat(l-1,B,l-1,i,-1);
            d[++tot]=dat(r,A-1,l-1,i,-1);
        }
        sort(d+1,d+tot+1);
        solve(1,tot);
        for(int i=1;i<=m;i++) printf("%d %d
    ",ans1[i],ans2[i]);
        return 0;
    }
  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11521620.html
Copyright © 2011-2022 走看看