• BZOJ3236: [Ahoi2013]作业


    Description

    Input

    Output

    Sample Input

    3 4
    1 2 2
    1 2 1 3
    1 2 1 1
    1 3 1 3
    2 3 2 3

    Sample Output

    2 2
    1 1
    3 2
    2 1

    HINT


    N=100000,M=1000000

     
    对权值建立线段树,对应询问在权值区间内打上标记,那么最后对线段树上的每个节点,问题就转化成HH的项链了。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    const int maxm=1000010;
    const int maxnode=20000010;
    int n,m,first[maxn],next[maxn],to[maxn],cnt;
    void AddVal(int u,int v) {
        next[++cnt]=first[u];to[cnt]=v;first[u]=cnt;
    }
    int L[maxm],R[maxm],ans[maxm],ans2[maxm],first2[maxn*3],next2[maxnode],to2[maxnode],ToT;
    void AddQuery(int u,int v) {
        next2[++ToT]=first2[u];to2[ToT]=v;first2[u]=ToT;
    }
    void query(int o,int l,int r,int ql,int qr,int val) {
        if(ql<=l&&r<=qr) AddQuery(o,val);
        else {
            int mid=l+r>>1,lc=o<<1,rc=lc|1;
            if(ql<=mid) query(lc,l,mid,ql,qr,val);
            if(qr>mid) query(rc,mid+1,r,ql,qr,val);
        }
    }
    struct Solver {
        int x,v,t;
        bool operator < (const Solver& ths) const {
            return x<ths.x;
        }
    }A[maxn],B[maxm];
    int sumv[maxn],clo[maxn],nxt[maxn],clo2[maxn],lst[maxn],T,T2;
    void add(int x,int v) {
        if(x>n) return;
        for(;x<=n;x+=x&-x) {
            if(clo[x]==T) sumv[x]+=v;
            else clo[x]=T,sumv[x]=v;
        }
    }
    int sum(int x) {
        int res=0;
        for(;x;x-=x&-x) if(clo[x]==T) res+=sumv[x];
        return res;
    }
    void solve(int o,int l,int r) {
        if(l!=r) {
            int mid=l+r>>1,lc=o<<1,rc=lc|1;
            solve(lc,l,mid);solve(rc,mid+1,r);
        }
        int m1=0,m2=0;
        rep(x,l,r) ren A[++m1]=(Solver){to[i],x,0};
        if(!m1||!first2[o]) return;
        T++;
        rep(i,1,m1) add(A[i].x,1);
        for(int i=first2[o];i;i=next2[i]) ans[to2[i]]+=sum(R[to2[i]])-sum(L[to2[i]]-1);
        T++;T2++;
        for(int i=first2[o];i;i=next2[i]) B[++m2]=(Solver){L[to2[i]],R[to2[i]],to2[i]};
        sort(A+1,A+m1+1);sort(B+1,B+m2+1);
        dwn(i,m1,1) {
            if(clo2[A[i].v]!=T2) clo2[A[i].v]=T2,lst[A[i].v]=i,nxt[i]=m1+1;
            else nxt[i]=lst[A[i].v],lst[A[i].v]=i;
        }T2++;
        rep(i,1,m1) if(clo2[A[i].v]!=T2) {
            clo2[A[i].v]=T2;
            add(A[i].x,1);
        }
        int j=1;
        rep(i,1,m2) {
            while(j<=m1&&A[j].x<B[i].x) {
                add(A[j].x,-1);
                if(nxt[j]<=m1) add(A[nxt[j]].x,1);
                j++;
            }
            ans2[B[i].t]+=sum(B[i].v)-sum(B[i].x-1);
        }
    }
    int main() {
        n=read();m=read();
        rep(i,1,n) AddVal(read(),i);
        rep(i,1,m) {
            L[i]=read();R[i]=read();
            int a=read(),b=read();
            query(1,1,n,a,b,i);
        }
        solve(1,1,n);
        rep(i,1,m) printf("%d %d
    ",ans[i],ans2[i]);
        return 0;
    }
    View Code

    莫队大法也很资瓷啊。对权值分块以牺牲询问复杂度的代价来降低修改复杂度。

    不知道为什么O(Msqrt(N))的做法比O(Mlog^2N)的做法快了3倍。。。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    const int maxm=1000010;
    int n,m,A[maxn],blo[maxn],st[maxn],en[maxn];
    struct Query {
        int l,r,a,b,id;
        bool operator < (const Query& ths) const {
            if(blo[l]==blo[ths.l]) return r<ths.r;
            return l<ths.l;
        }
    }Q[maxm];
    int ans[maxm],ans2[maxm],cnt[maxn],sum[maxn],bloans[maxn];
    void add(int x) {
        if(!cnt[x]) bloans[blo[x]]++;
        cnt[x]++;sum[blo[x]]++;
    }
    void del(int x) {
        cnt[x]--;sum[blo[x]]--;
        if(!cnt[x]) bloans[blo[x]]--;
    }
    void query(int x,int l,int r) {
        rep(i,blo[l]+1,blo[r]-1) ans2[x]+=bloans[i],ans[x]+=sum[i];
        if(blo[l]==blo[r]) rep(i,l,r) ans2[x]+=(cnt[i]>0),ans[x]+=cnt[i];
        else {
            rep(i,l,en[blo[l]]) ans2[x]+=(cnt[i]>0),ans[x]+=cnt[i];
            rep(i,st[blo[r]],r) ans2[x]+=(cnt[i]>0),ans[x]+=cnt[i];
        }
    }
    int main() {
        n=read();m=read();int SIZE=(int)sqrt(n);
        rep(i,1,n) {
            A[i]=read();blo[i]=(i-1)/SIZE+1;
            if(!st[blo[i]]) st[blo[i]]=i;
            en[blo[i]]=i;
        }
        rep(i,1,m) Q[i].l=read(),Q[i].r=read(),Q[i].a=read(),Q[i].b=read(),Q[i].id=i;
        sort(Q+1,Q+m+1);
        int l=1,r=0;
        rep(i,1,m) {
            while(l>Q[i].l) add(A[--l]);
            while(r<Q[i].r) add(A[++r]);
            while(l<Q[i].l) del(A[l++]);
            while(r>Q[i].r) del(A[r--]);
            query(Q[i].id,Q[i].a,Q[i].b);
        }
        rep(i,1,m) printf("%d %d
    ",ans[i],ans2[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    JavaScript中对事件简单的理解
    正则表达式 RE模块
    模块
    面向对象进阶
    元类详细解释
    四.面向对象和函数补充
    四.函数
    Python的基础知识:
    五层协议及tcp三次握手四次挥手
    nginx常见错误
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5279983.html
Copyright © 2020-2023  润新知