• bzoj2141 树状数组套Treap树


    题目大意是在能够改变两个数的位置的情况下计算逆序对数

    这因为是动态记录逆序对

    本来单纯逆序对只要用树状数组计算即可,但这里因为更新,所以利用TReap树的删点和增加点来进行更新

    大致是把每个树状数组所管理的点都放在对应的Treap树下,

    这样x-=lowbit(x)下来,正好访问到是所有比他小范围下的点了

    然后根据每棵访问到的Treap树有多少个节点是比当前值小的即可

    每次交换ai , aj , (i<j)只要考虑(i,j)范围内比ai大的数,比aj小的数,然后加加减减即可

    如果ai!=aj也是要加减1

      1 #include <bits/stdc++.h>
      2   
      3 using namespace std;
      4 #define N 20005
      5   
      6 struct Node{
      7     int l , r , val , sz , pri , cnt;
      8     //cnt表示当前位置相同的数有多少个,pri表示优先级,sz表示这棵子树所含有的节点总个数
      9     Node(){
     10         l = r = 0;
     11         cnt = sz = 1 , pri = rand();
     12         val = 0;
     13     }
     14     Node(int v){
     15         Node();
     16         val = v;
     17     }
     18 };
     19 #define ls node[x].l
     20 #define rs node[x].r
     21 namespace Treap{
     22     int tot;//Treap Node节点的总个数
     23     int A[N];//有n棵treap树,A[]表示每棵treap树的起始位置
     24     Node node[N*50];
     25     void init(){
     26         node[0] = Node();
     27         node[0].cnt = node[0].sz = 0;
     28         memset(A , 0 , sizeof(A));
     29         tot = 0;
     30     }
     31     int newNode(int v){
     32         ++tot;
     33         node[tot].cnt = node[tot].sz = 1;
     34         node[tot].l = node[tot].r = 0;
     35         node[tot].pri = rand();
     36         node[tot].val = v;
     37         return tot;
     38     }
     39     void push_up(int x) {
     40        // cout<<"here: "<<x<<" "<<ls<<" "<<rs<<endl;
     41         if(x>0)
     42             node[x].sz = node[ls].sz+node[rs].sz+node[x].cnt;
     43     }
     44     void rotL(int &x){
     45         int y = rs;
     46         rs = node[y].l;
     47         node[y].l = x;
     48   
     49         push_up(x);
     50         push_up(y);
     51         x = y;
     52     }
     53     void rotR(int &x){
     54         int y = ls;
     55         ls = node[y].r;
     56         node[y].r = x;
     57   
     58         push_up(x);
     59         push_up(y);
     60         x = y;
     61     }
     62     void insert(int &x , int v){
     63     //    cout<<x<<" "<<v<<endl;
     64         if(x == 0) x = newNode(v);
     65         else if(node[x].val>v){
     66             insert(ls , v);
     67             if(node[ls].pri>node[x].pri) rotR(x);
     68         }
     69         else if(node[x].val<v){
     70             insert(rs , v);
     71             if(node[rs].pri>node[x].pri) rotL(x);
     72         }
     73         else node[x].cnt++;
     74         push_up(x);
     75        // cout<<x<<" "<<v<<" "<<"endd"<<endl;
     76     }
     77     void erase(int &x , int v){
     78         if(x == 0) return ;
     79         else if(v<node[x].val) erase(ls , v);
     80         else if(v>node[x].val) erase(rs , v);
     81         else {
     82             node[x].cnt--;
     83             if(node[x].cnt<=0){
     84                 if(ls==0&&rs==0) x = 0;
     85                 else if(ls == 0) x = rs;
     86                 else if(rs == 0) x = ls;
     87                 else{
     88                     if(node[ls].pri <node[rs].pri) rotL(x),erase(ls,v);
     89                     else rotR(x) , erase(rs , v);
     90                 }
     91             }
     92         }
     93         push_up(x);
     94     }
     95     int getCnt(int x , int v){//从x号节点出发找到对应的子树下小于等于v的值的个数
     96         if(x == 0) return 0;
     97         int ans = 0;
     98         if(node[x].val>v) ans = getCnt(ls , v);
     99         else if(node[x].val<v) ans = node[x].cnt+node[ls].sz+getCnt(rs , v);
    100         else ans = node[x].cnt+node[ls].sz;
    101         return ans;
    102     }
    103 }
    104 int n , m , h[N] , a[N] , tot;
    105 //树状数组部分
    106 #define lowbit(x) x&(-x)
    107 void Add(int id , int v)
    108 {
    109     for(int x=id ; x<=n ; x+=lowbit(x)){
    110         Treap::insert(Treap::A[x] , v);
    111     }
    112 }
    113 void Erase(int id , int v)
    114 {
    115     for(int x=id ; x<=n ; x+=lowbit(x)){
    116         Treap::erase(Treap::A[x] , v);
    117     }
    118 }
    119 int getSum(int p , int v)//cal 1~p区间内小于等于v的值的个数
    120 {
    121     int sum = 0;
    122     for(int x=p ; x>0 ; x-=lowbit(x)){
    123         sum+=Treap::getCnt(Treap::A[x] , v);
    124     }
    125     return sum;
    126 }
    127 int getSumMin(int p , int v)//cal 1~p区间内小于v的值的个数
    128 {
    129     v--;//important保证等于的情况被排除
    130     return getSum(p , v);
    131 }
    132   
    133 int main()
    134 {
    135    // freopen("a.in" , "r" , stdin);
    136     scanf("%d" , &n);
    137     for(int i=1 ; i<=n ; i++){
    138         scanf("%d" , &h[i]);
    139         a[i] =  h[i];
    140     }
    141     sort(a+1 , a+n+1);
    142     tot = unique(a+1 , a+n+1)-(a+1);
    143     Treap::init();
    144     int sum = 0;
    145     for(int i=1 ; i<=n ; i++){
    146         h[i] = lower_bound(a+1 , a+tot+1 , h[i])-a;
    147         Add(i , h[i]);
    148         sum+=i-1-getSum(i-1 , h[i]);
    149     }
    150     printf("%d
    " , sum);
    151   
    152     scanf("%d" , &m);
    153     while(m--){
    154 //        for(int i=1 ; i<=n ; i++)
    155 //            cout<<h[i]<<" ";
    156 //        cout<<endl;
    157         int ai , bi;
    158         scanf("%d%d" , &ai , &bi);
    159         if(ai>bi) swap(ai , bi);
    160         if(h[ai]<h[bi]) sum++;
    161         else if(h[ai]>h[bi]) sum--;
    162         else{
    163             printf("%d
    " , sum);
    164             continue;
    165         }
    166         int add = 0;
    167         if(bi-ai>1){
    168             add += getSumMin(bi-1 , h[bi])-getSumMin(ai , h[bi]);
    169             add -= (bi-ai-1)-(getSum(bi-1 , h[bi])-getSum(ai , h[bi]));
    170             add += (bi-ai-1)-(getSum(bi-1 , h[ai])-getSum(ai , h[ai]));
    171             add -= getSumMin(bi-1 , h[ai])-getSumMin(ai , h[ai]);
    172         }
    173   
    174         sum += add;
    175   
    176         Erase(ai , h[ai]);
    177         Erase(bi , h[bi]);
    178         Add(ai , h[bi]);
    179         Add(bi , h[ai]);
    180         swap(h[ai] , h[bi]);
    181         printf("%d
    " , sum);
    182     }
    183     return 0;
    184 }
  • 相关阅读:
    jQuery 重新温习 遗忘知识点
    正则表达式获取博客园随笔1
    用django创建一个简单的sns
    WCF小实例以及三种宿主
    iOS: imageIO完成渐进加载图片
    Excel 菜单系统
    分布式EventBus的Socket实现
    Jenkins安装plugin
    邮件系统存储设计问答
    在Windows上使用CodeLite+MinGW+Clang进行开发
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/5369785.html
Copyright © 2020-2023  润新知