blog正式转移到了这里:

http://blog.phoeagon.cz.cc



I know

phoeagon啲01世界

2009 年 12 月 4 日  星期五   晴天


Counting Inversions 分類: Code Storage

Counting Inversions.

You are given a sequence A of N (N≤250000) integers between 1 and 50000. On this sequence you have to apply M (M≤10000) operations of the form: modify the i-th element in the sequence and then say how many inversions are there in the sequence. The number of inversions in a sequence is given by the number of pairs (i,j) with i < j and Ai > Aj.

 

straight-forward algorithm: using a inteval tree with a binary indexed tree in each node and maintaining such a structure.

as the memory usage will be too large if we store all the N^2 possible intervals, we just split it into larger intervals and if a interval is smaller than a specific number, then stop processing its sub-intervals. when it's neccessary to query such small intervals, use brute force way to calculate.

really slow and takes lots of memory though, no wonder it's a straight-forward way.

 

#include <stdio.h>
#include <math.h>
#include <cstring>
using namespace std;

const int maxn=250010;
const int maxr=50010;
const int treesize=520*2;
int size;
long long ans;
int limit;
int tree[treesize][maxr];
int nk[treesize];
int dt[maxn];
int n,m;


             inline int lowbit(int x){ return x & (-x);}
            
             inline void update(int seg,int nd,int dt){
                    while (nd<maxr){
                          tree[seg][nd]+=dt;
                          nd+=lowbit(nd);
                          }
                    }
                   
             inline int sum(int seg,int nd){
                    int ans=0;
                    while (nd>0){
                          ans+=tree[seg][nd];
                          nd-=lowbit(nd);
                          }
                    return ans;
                    }
                   
             void make_tree(int nd,int l,int r){
                  //size = size>nd?size:nd;
                  if (r-l>limit){
                                int m = (l+r)>>1;
                                make_tree(nd*2,l,m);
                                make_tree(nd*2+1,m+1,r);
                  }
                  else nk[nd]=1;
                  }
                 
             void modify(int nd,int l,int r,int des,int x,int y){
                  if (x!=0)
                        update(nd,x,-1);
                  update(nd,y,1);
                  if (nk[nd]==0){
                     int m=(l+r)>>1;
                     if (des>m)
                        modify(nd*2+1,m+1,r,des,x,y);
                     else modify(nd*2,l,m,des,x,y);
                  }
                  }
                 
             int getnum(int nd,int l,int r,int s,int t,int x,int y){
                 if (s>n||y<1)return 0;
                  if (s==l&&t==r){
                       return sum(nd,y)-sum(nd,x-1);         
                  };
                  int m=(l+r)>>1;
                  if (nk[nd]){
                     int i;
                     int ans=0;
                     for (i=s;i<=t;++i)
                          if (dt[i]>=x&&dt[i]<=y)++ans;
                     return ans;
                  }
                  else {
                      m=(l+r)>>1;
                      if (s>m)
                         return getnum(nd*2+1,m+1,r,s,t,x,y);
                      else if (t<=m)
                           return getnum(nd*2,l,m,s,t,x,y);
                      else return getnum(nd*2,l,m,s,m,x,y)+getnum(nd*2+1,m+1,r,m+1,t,x,y);
                  }
                  }
                 
             void work(){
                  scanf("%ld",&n);
                  limit=int(sqrt(n));
                  make_tree(1,1,n);
                 
                  int i,j,a,b;
                  ans=0;
                  for (i=1;i<=n;++i)
                      scanf("%ld",&dt[i]);
                  for (i=n;i>=1;--i){
                      ans+=sum(1,dt[i]-1);
                     modify(1,1,n,i,0,dt[i]);
                      }
                     
                  //now ans is the current inversion
                 
                  scanf("%ld",&m);
                  int x,y;
                 
                  for (i=1;i<=m;++i){
                      scanf("%ld%ld",&a,&b);
                      if (b>dt[a]){
                             x=getnum(1,1,n,1,a-1,dt[a]+1,b);
                             y=getnum(1,1,n,a+1,n,dt[a],b-1);
                             ans=ans-x+y;
                      }
                      else if(b<dt[a]){
                           x=getnum(1,1,n,1,a-1,b+1,dt[a]);
                           y=getnum(1,1,n,a+1,n,b,dt[a]-1);
                           ans=ans+x-y;
                      }
                      modify(1,1,n,a,dt[a],b);
                      dt[a]=b;
                      printf("%lld\n",ans);
                      }
                  }
             int main(){
                 work();
                // limit=250;
                // make_tree(1,1,250000);
                //  printf("%ld",size);  
                 }
            
 






訪客留言 (返回 phoeagon 的日誌)

訪客名稱:
電郵地址: (不會公開)
驗證碼:  按此更新驗證碼 (如看不清楚驗證碼請點擊圖片刷新)
俏俏話: (必需 登入 後才能使用此功能)
[ 開啟多功能編輯器 ]







人氣:79257
暱稱: phoeagon
性別: 男
MORE...  
« May 2019 »
SMTWTFS
1234
567891011
12131415161718
19202122232425
262728293031
» 最新日誌
Blog Moved!
跨站jsMath实现
路由表是个好东西
Twitter Fav列表达陈100...
搞定了公式显示
» 日誌分類
全部 (175)
Code Storage (11)
Math&Phy@Chem@MM (8)
Music Anyway (5)
Programming Impossible (28)
RSS提示 (2)
StorageBox (5)
'Bout Here (12)
滑鼠人生 (42)
碎屑 (51)
未分類 (11)
» 訪客留言
最近三個月尚無任何留言
» 最近訪客
最近沒有訪客
» 每月文章
» 日誌訂閱
尚未訂閱任何日誌
» 我的好友
» 我的連結
Ink Mark --Jlim
StarKirby
|S||S||S|
「流年祭」
» 日誌統計
文章總數: 175
留言總數: 86
今日人氣: 27
累積人氣: 79257
» 站內搜索
RSS Feed