zoukankan      html  css  js  c++  java
  • LG P1975 [国家集训队]排队

    Description

    排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。

    红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第 ii个小朋友的身高为 hi

    幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的逆序对数。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的逆序对数。

    Solution

    这道题最经典的做法就是树状数组套平衡树了,做法与动态逆序对比较像 考虑交换两个数之后产生的贡献:

    不妨设 $a<b$

    原来的区间$[a,b]$中:

    比$h[b]$小的数,原来不组成逆序对,交换之后组成了

    比$h[b]$大的数,原来组成逆序对,交换之后消失了

    比$h[a]$大的数,原来不组成逆序对,交换之后组成了

    比$h[a]$小的数,原来组成逆序对,交换之后消失了

    分别统计计算贡献,我的树状数组以身高为下标,每个位置存放一个平衡树存储该身高出现的位置。

    不要忘记计算两个人交换时这两个人组成的逆序对产生的贡献

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstdlib>
      4 #include<cstdio>
      5 using namespace std;
      6 int n,m,h[20005],s[20005],ans[2005],bit[20005],tot,root[20005],cnt;
      7 struct BST
      8 {
      9     int key,siz,val,child[2];
     10 }treap[4000005];
     11 inline int read()
     12 {
     13     int f=1,w=0;
     14     char ch=0;
     15     while(ch<'0'||ch>'9')
     16     {
     17         if(ch=='-')
     18             f=-1;
     19         ch=getchar();
     20     }
     21     while(ch>='0'&&ch<='9')
     22     {
     23         w=(w<<1)+(w<<3)+ch-'0';
     24         ch=getchar();
     25     }
     26     return f*w;
     27 }
     28 int lowbit(int x)
     29 {
     30     return x&-x;
     31 }
     32 int query(int x)
     33 {
     34     int ret=0;
     35     while(x)
     36     {
     37         ret+=bit[x];
     38         x-=lowbit(x);
     39     }
     40     return ret;
     41 }
     42 void add(int x)
     43 {
     44     while(x<=tot)
     45     {
     46         bit[x]++;
     47         x+=lowbit(x);
     48     }
     49 }
     50 void pushup(int rt)
     51 {
     52     treap[rt].siz=treap[treap[rt].child[0]].siz+treap[treap[rt].child[1]].siz+1;
     53 }
     54 void split(int rt,int &x,int &y,int v)
     55 {
     56     if(!rt)
     57     {
     58         x=y=0;
     59         return;
     60     }
     61     if(treap[rt].val<=v)
     62     {
     63         x=rt;
     64         split(treap[rt].child[1],treap[x].child[1],y,v);
     65     }
     66     else
     67     {
     68         y=rt;
     69         split(treap[rt].child[0],x,treap[y].child[0],v);
     70     }
     71     pushup(rt);
     72 }
     73 void merge(int &rt,int x,int y)
     74 {
     75     if(!x||!y)
     76     {
     77         rt=x+y;
     78         return;
     79     }
     80     if(treap[x].key<treap[y].key)
     81     {
     82         rt=x;
     83         merge(treap[rt].child[1],treap[x].child[1],y);
     84     }
     85     else
     86     {
     87         rt=y;
     88         merge(treap[rt].child[0],x,treap[y].child[0]);
     89     }
     90     pushup(rt);
     91 }
     92 int check(int &rt,int l,int r)
     93 {
     94     int x=0,y=0,z=0;
     95     split(rt,x,z,r);
     96     split(x,x,y,l-1);
     97     int ret=treap[y].siz;
     98     merge(x,x,y);
     99     merge(rt,x,z);
    100     return ret;
    101 }
    102 int queryarr(int x,int l,int r)
    103 {
    104     int ret=0;
    105     while(x)
    106     {
    107         ret+=check(root[x],l,r);
    108         x-=lowbit(x);
    109     }
    110     return ret;
    111 }
    112 void erase(int &rt,int v)
    113 {
    114     int x=0,y=0,z=0;
    115     split(rt,x,z,v);
    116     split(x,x,y,v-1);
    117     merge(y,treap[y].child[0],treap[y].child[1]);
    118     merge(x,x,y);
    119     merge(rt,x,z);
    120 }
    121 void insert(int &rt,int v)
    122 {
    123     int x=0,y=0,z=++cnt;
    124     treap[z].siz=1;
    125     treap[z].val=v;
    126     treap[z].key=rand();
    127     split(rt,x,y,v);
    128     merge(x,x,z);
    129     merge(rt,x,y);
    130 }
    131 void addarr(int x,int pos,int v)
    132 {
    133     while(x<=tot)
    134     {
    135         if(v==-1)
    136             erase(root[x],pos);
    137         else
    138             insert(root[x],pos);
    139         x+=lowbit(x);
    140     }
    141 }
    142 int main()
    143 {
    144     n=read();
    145     for(int i=1;i<=n;i++)
    146         s[i]=h[i]=read();
    147     sort(s+1,s+n+1);
    148     tot=unique(s+1,s+1+n)-s-1;
    149     for(int i=1;i<=n;i++)
    150         h[i]=lower_bound(s+1,s+1+tot,h[i])-s;
    151     for(int i=1;i<=n;i++)
    152     {
    153         ans[0]+=query(tot)-query(h[i]);
    154         add(h[i]);
    155         addarr(h[i],i,1);
    156     }
    157     printf("%d
    ",ans[0]);
    158     m=read();
    159     for(int i=1;i<=m;i++)
    160     {
    161         ans[i]=ans[i-1];
    162         int a=read(),b=read();
    163         if(a>b)
    164             swap(a,b);
    165         if(b-a>1)
    166         {
    167             ans[i]+=queryarr(h[b]-1,a+1,b-1);
    168             ans[i]-=queryarr(tot,a+1,b-1)-queryarr(h[b],a+1,b-1);
    169             ans[i]-=queryarr(h[a]-1,a+1,b-1);
    170             ans[i]+=queryarr(tot,a+1,b-1)-queryarr(h[a],a+1,b-1);    
    171         }
    172         addarr(h[a],a,-1);
    173         addarr(h[b],b,-1);
    174         addarr(h[a],b,1);
    175         addarr(h[b],a,1);
    176         if(h[a]<h[b])
    177             ans[i]++;
    178         else if(h[a]>h[b])
    179             ans[i]--;
    180         swap(h[a],h[b]);
    181         printf("%d
    ",ans[i]);
    182     }
    183     return 0;
    184 }
    P1975 【[国家集训队]排队】
  • 相关阅读:
    python实例
    date命令
    unbuntu禁用ipv6
    Oracle学习(一)
    深入浅出区块链笔记
    sqlserver索引
    Go学习(16):网络编程
    Go学习(15):并发与包
    Go学习(14):defer
    Go学习(13):异常
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13301569.html
Copyright © 2011-2022 走看看