• [bzoj3289]Mato的文件管理


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号。为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料。Mato有一个习惯,他总是从文件大小从小到大看资料。他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能随机访问)。Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?  n<=50000

    求的是区间的逆序对数量... 所以直接莫队+线段树转移就行了。复杂度$O(n^{frac{3}{2}}logn)$

    当然还可以分块,选择根号个点,处理出每个点到所有点的答案,然后每次询问暴力跳 上个主席树查逆序对数量就行了  复杂度一样 但是支持在线

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define MN 50000
    #define N 65534
    #define ll long long
    using namespace std;
    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 * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,s[MN+5],m,cnt=1,size,block[MN+5],T[N*2+5],L,R,l[MN+5];
    struct ques{int l,r,id;}q[MN+5];
    bool cmp(ques x,ques y){return block[x.l]==block[y.l]?x.r<y.r:x.l<y.l;}
    ll ans=0,Ans[MN+5];
    
    inline int query(int l,int r)
    {
        if(l>r) return 0;int sum=0;
        for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1) sum+=T[l+1];
            if( r&1) sum+=T[r-1];    
        }
        return sum;
    }
    
    void renew(int x,int ad)
    {
        T[x+=N]+=ad;
        for(x>>=1;x;x>>=1) T[x]=T[x<<1]+T[x<<1|1];    
    }
    
    inline void insL(int x,int ad)
    {
        ans+=ad*query(1,s[x]-1);    
        renew(s[x],ad);
    }
    
    inline void insR(int x,int ad)
    {
        ans+=ad*query(s[x]+1,cnt);
        renew(s[x],ad);    
    }
    
    int main()
    {
        n=read();size=sqrt(n);
        for(int i=1;i<=n;++i) block[i]=(i-1)/size+1;
        for(int i=1;i<=n;++i) s[i]=l[i]=read();    
        sort(l+1,l+n+1);
        for(int i=2;i<=n;++i) if(s[i]!=s[i-1]) s[++cnt]=s[i]; 
        for(int i=1;i<=n;++i) s[i]=lower_bound(l+1,l+cnt+1,s[i])-l;
        m=read();
        for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].id=i;
        sort(q+1,q+m+1,cmp);
        for(int i=1,last=0;i<=m;++i)
        {
            if(block[q[i].l]!=last) 
            {
                memset(T,0,sizeof(T));
                insL(L=R=(block[q[i].l]-1)*size+1,1);    
                last=block[q[i].l];ans=0;
            }
            while(L<q[i].l) insL(L++,-1);
            while(L>q[i].l) insL(--L, 1);
            while(R<q[i].r) insR(++R, 1);
            Ans[q[i].id]=ans;
        }
        for(int i=1;i<=m;++i) printf("%lld
    ",Ans[i]);
        return 0;
    }
  • 相关阅读:
    在基础数据类型和在对象中 使用 == 与equals的差别
    对Java中静态代理和动态代理的简单理解
    MyBatis中sqlSession的创建及执行流程
    Spring相关概念
    AOP相关
    IOC容器和Bean的配置
    如何将本地项目上传到GitHub进行托管
    稀疏数组
    Java集合回忆
    JSTL标签库
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3289.html
Copyright © 2020-2023  润新知