zoukankan      html  css  js  c++  java
  • 【bzoj3289】 Mato的文件管理

    http://www.lydsy.com/JudgeOnline/problem.php?id=3289 (题目链接)

    题意

      求区间逆序对

    Solution

      离线无修改查询,莫队转移;树状数组维护区间和。

      关键: 
       ①在一列数的后面添加一个数,逆序对数会增加 数列中比它大的数的个数。 
       ②在一列数的后面删除一个数,逆序对数会减少 数列中比它大的数的个数。 
       ③在一列数的前面添加一个数,逆序对数会增加 数列中比它小的数的个数。 
       ④在一列数的前面删除一个数,逆序对数会减少 数列中比它小的数的个数。

      这样一来就做法就很显然了。

    代码

    // bzoj3289
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define inf 2147483640
    #define LL long long
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        LL x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=50010;
    struct ask {int l,r,id;}t[maxn];
    int pos[maxn],a[maxn],b[maxn],c[maxn],ans[maxn],block,n,m,q;
    
    int lowbit(int x) {
        return x&-x;
    }
    void add(int x,int val) {
        for (int i=x;i<=m;i+=lowbit(i)) c[i]+=val;
    }
    int query(int x) {
        int t=0;
        for (int i=x;i>=1;i-=lowbit(i)) t+=c[i];
        return t;
    }
    bool cmp(ask a,ask b) {
        return pos[a.l]==pos[b.l] ? a.r<b.r : pos[a.l]<pos[b.l];
    }
    int main() {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
        scanf("%d",&q);
        for (int i=1;i<=q;i++) scanf("%d%d",&t[i].l,&t[i].r),t[i].id=i;
        sort(b+1,b+1+n);
        m=unique(b+1,b+1+n)-b-1;
        for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+m,a[i])-b;
        block=(int)sqrt(n);
        for (int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
        sort(t+1,t+1+q,cmp);
        int res=0;
        for (int i=1,l=1,r=0;i<=q;i++) {
            for (;r<t[i].r;r++)
                res+=r+1-l-query(a[r+1]),add(a[r+1],1);
            for (;r>t[i].r;r--)
                res-=r-l-query(a[r]-1),add(a[r],-1);
            for (;l<t[i].l;l++)
                res-=query(a[l]-1),add(a[l],-1);
            for (;l>t[i].l;l--)
                res+=query(a[l-1]),add(a[l-1],1);
            ans[t[i].id]=res;
        }
        for (int i=1;i<=q;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    组合继承
    包装明星——封装
    多种添加公用方法的方式
    专有扩展
    插入标记
    mac 命令操作
    php(apache)切换版本
    SqlServer索引+约束篇章
    sqlserver 常用语法
    C# 通用数据访问类
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914536.html
Copyright © 2011-2022 走看看