题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2141

题意:给出一个数列A,每次交换两个数的位置。输出交换后逆序对的个数。

思路:首先,对于交换位置x和y,对于区间[x+1,y-1]的数字,小于A[x]的要减去,大于A[x]的要加上,大于A[y]的要减去,小于A[y] 的要加上。然后A[x]<A[y]则答案加1,A[x]<A[y]答案要减去1。查找修改用树状数组套一个treap即可。

struct node
{
    int val,size,pri,L,R,cnt;
};
  
  
node a[N*300];
int e;
  
 
int newNode(int val)
{
    int x=++e;;
    a[x].val=val;
    a[x].size=1;
    a[x].cnt=1;
    a[x].L=a[x].R=0;
    a[x].pri=rand();
    return x;
}
 
void pushUp(int x)
{
    if(x==0) return;
    a[x].size=a[x].cnt+a[a[x].L].size+a[a[x].R].size;
}
 
void rotL(int &x)
{
    int y=a[x].R;
    a[x].R=a[y].L;
    a[y].L=x;
      
    pushUp(x);
    pushUp(y);
    x=y;
}
  
void rotR(int &x)
{
    int y=a[x].L;
    a[x].L=a[y].R;
    a[y].R=x;
      
    pushUp(x);
    pushUp(y);
    x=y;
}
  
void insert(int &k,int val)
{
    if(k==0) k=newNode(val);
    else if(val<a[k].val) 
    {
        insert(a[k].L,val);
        if(a[a[k].L].pri>a[k].pri) rotR(k);
    }
    else if(val>a[k].val)
    {
        insert(a[k].R,val);
        if(a[a[k].R].pri>a[k].pri) rotL(k);
    }
    else a[k].cnt++;
    pushUp(k);
}
  
void del(int val,int &k)
{
    if(k==0) return;
    else if(val<a[k].val) del(val,a[k].L);
    else if(val>a[k].val) del(val,a[k].R);
    else
    {
        a[k].cnt--;
        if(a[k].cnt<=0)
        {
            if(a[k].L==0&&a[k].R==0) k=0;
            else if(a[k].L==0) k=a[k].R;
            else if(a[k].R==0) k=a[k].L;
            else
            {
                if(a[a[k].L].pri<a[a[k].R].pri) rotL(k),del(val,a[k].L);
                else rotR(k),del(val,a[k].R);
            }
        }
    }
    pushUp(k);
}
  
int d[N];
  
int getCnt(int t,int x)
{
    if(t==0) return 0;
    if(a[t].val==x) 
    {
        return a[a[t].L].size+a[t].cnt;
    }
    if(a[t].val>x) return getCnt(a[t].L,x);
    return a[t].cnt+a[a[t].L].size+getCnt(a[t].R,x);
}
 
 
int n,m;
int A[N];
  
void Set(int x,int k)
{
    while(x<=n) 
    {
        insert(A[x],k);
        x+=x&-x;
    }
}
 
void erase(int x,int k)
{
    while(x<=n) 
    {
        del(k,A[x]);
        x+=x&-x;
    }
}
 
int get(int x,int k)
{
    int ans=0;
    while(x) 
    {
        ans+=getCnt(A[x],k);
        x-=x&-x;
    }
    return ans;
}
  
pair<int,int> cal(int L,int R,int x)
{
    i64 a=get(R,x)-get(L-1,x);
    i64 b=get(R,x-1)-get(L-1,x-1);
    return MP(a-b,b);

 
int p[N];
 
int find(int low,int high,int x)
{
    int M;
    while(low<=high)
    {
        M=(low+high)>>1;
        if(p[M]==x) return M;
        if(p[M]>x) high=M-1;
        else low=M+1;
    }
}
  
void getInt(int &x)
{
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    x=0;
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
  
int main()
{
    getInt(n);
    int i;
    FOR1(i,n) getInt(d[i]),p[i]=d[i];
    sort(p+1,p+n+1);
    int M=unique(p+1,p+n+1)-(p+1);
    FOR1(i,n) d[i]=find(1,M,d[i]);
    i64 sum=0;
    pair<int,int> temp;
    FOR1(i,n) 
    {
        Set(i,d[i]);
        temp=cal(1,i-1,d[i]);
        sum+=i-1-temp.first-temp.second;
    }
     
    PR(sum);
    RD(m);
    int x,y;
    while(m--)
    {
        getInt(x);
        getInt(y);
        if(x>y) swap(x,y);
        if(d[x]==d[y])
        {
            PR(sum);
            continue;
        }
         
        if(d[x]>d[y]) sum--;
        else sum++;
         
        if(y-x>1) 
        {
            temp=cal(x+1,y-1,d[x]);
            sum-=temp.second;
            sum+=y-x-1-temp.first-temp.second;
              
            temp=cal(x+1,y-1,d[y]);
            sum+=temp.second;
            sum-=y-x-1-temp.first-temp.second;
        }
         
        erase(x,d[x]);
        erase(y,d[y]);
        swap(d[x],d[y]);
        Set(x,d[x]);
        Set(y,d[y]);
         
        PR(sum);
    }
}

BZOJ 2141 排队(树状数组套treap)的更多相关文章

  1. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  2. BZOJ - 3295 动态逆序对 (树状数组套treap)

    题目链接 思路和bzoj2141差不多,不过这道题的数据更强一些,线段树套treapT了,树状数组套treap卡过~~ #include<bits/stdc++.h> using name ...

  3. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  4. bzoj2141 树状数组套Treap树

    题目大意是在能够改变两个数的位置的情况下计算逆序对数 这因为是动态记录逆序对 本来单纯逆序对只要用树状数组计算即可,但这里因为更新,所以利用TReap树的删点和增加点来进行更新 大致是把每个树状数组所 ...

  5. HDU 5618 Jam's problem again (cdq分治+BIT 或 树状数组套Treap)

    题意:给n个点,求每一个点的满足 x y z 都小于等于它的其他点的个数. 析:三维的,第一维直接排序就好按下标来,第二维按值来,第三维用数状数组维即可. 代码如下: cdq 分治: #pragma ...

  6. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  7. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...

  8. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  9. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

随机推荐

  1. Chrome浏览器扩展 获取用户密码

    Chrome 浏览器允许安装第三方扩展程序以扩展浏览器并给浏览器加入新的功能,扩展使用 JavaScript 以及 HTMl 编写并允许互相访问和控制 DOM. 因为允许访问 DOM,攻击者就可以读取 ...

  2. mysqli_report

    MYSQLI_REPORT_OFF Turns reporting off MYSQLI_REPORT_ERROR Report errors from mysqli function calls M ...

  3. 网站搜索引擎优化(SEO)的18条守则

    1.永远不要放过网页的title,这个地方应该是你每次优化的重点. 2.请不要在title,deion,keyword里写太多东西,越是贪婪,得到的就越少. 3.网页的头部和底部是很重要的,对于搜索引 ...

  4. Vue打开新页面的方法

    let routeData = this.$router.resolve({ name: "detail", query: {goodsId:'1111'} }); window. ...

  5. SQL Server 登录名、服务器角色、用户名和数据库角色 --- 解释

    一.基本解释 登录名:登录服务器的用户账号: 服务器角色:登录名对该服务器具有的权限,角色分多种的,一个角色可以有多个登录名,如操作系统的系统用户可以有多个. SQL服务器角色  sysadmin   ...

  6. APICloud-端JS库功能API文档(1)

    框架简介: 框架基于APICloud官网端API进行扩展和封装,框架完全采用面向对象编程形式,里面包含APP所使用的常用js功能:js类的自定义(类,构造方法,静态方法,继承...),常用工具函数(验 ...

  7. [py]flask实现用户cmdb

    人最难做到的就是跟自己学习, 总是学习别人的, 沉淀, 过一段时间忘了刚学到的, 在向别人学习, 而非看看自己的沉淀, 殊不知, 世界上最亲近,最默契的人是自己. 用户cmdb功能概述 之前学flas ...

  8. [py]django强悍的数据库接口(QuerySet API)-增删改查

    django强悍的数据库接口(QuerySet API) 4种方法插入数据 获取某个对象 filter过滤符合条件的对象 filter过滤排除某条件的对象- 支持链式多重查询 没找到排序的 - 4种方 ...

  9. Appium-Python-Client安装

    官网是这个:https://pypi.org/project/Appium-Python-Client/#files 下载下来后是这样的文件不知道怎么安装: 不用下载,直接这样就可以 了~~ 安装后导 ...

  10. [LeetCode] 103. Binary Tree Zigzag Level Order Traversal _ Medium tag: BFS

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...