【[CQOI2011]動態逆序對】
阿新 • • 發佈:2019-01-01
這是我的第一個資料結構套資料結構
不是線段樹套\(Splay\),而是非常蛇皮的塊狀連結串列套樹狀陣列
如果這裡按照\(\sqrt{n}\)的大小來分塊,那麼就需要\(n\sqrt{n}\)的空間,可能開不下,於是我們按照\(1000\)分塊,也就只會分出\(100\)個塊,就能開下空間了
之後每一次查詢的時候直接查詢樹狀陣列就好了,每次修改則非常的塊,直接找到對應的塊改動這個塊的樹狀陣列就好了
程式碼
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #define lowbit(x) ((x)&(-x)) #define re register #define maxn 100005 #define LL long long #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) int a[maxn],b[maxn]; int l[1005],r[1005],sz[1005]; inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } int c[maxn]; int bit[101][maxn]; int n,m,tot,len; LL ans; int to[maxn],vis[maxn]; inline void add(int x) { for(re int i=x;i<=n;i+=lowbit(i)) c[i]++; } inline int ask(int x) { int now=0; for(re int i=x;i;i-=lowbit(i)) now+=c[i]; return now; } inline void get_pair() { for(re int i=1;i<=n;i++) { ans+=ask(n)-ask(a[i]); add(a[i]); } } inline void B_add(int o,int x,int val) { for(re int i=x;i<=n;i+=lowbit(i)) bit[o][i]+=val; } inline int B_ask(int o,int x) { int now=0; for(re int i=x;i;i-=lowbit(i)) now+=bit[o][i]; return now; } inline void build_block() { len=1000; int k=1; while(k<=n) { l[++tot]=k; r[tot]=min(n,k+len-1); k=r[tot]+1; for(re int i=l[tot];i<=r[tot];i++) B_add(tot,a[i],1); } } inline int get_num(int x) { if(x%len==0) return x/len; return x/len+1; } inline void BL_change(int x) { vis[to[x]]=1; int now=get_num(to[x]); B_add(now,x,-1); } inline int BL_find_less(int x,int y,int val) { int num=0; for(re int i=x;i<=y;i++) if(!vis[i]&&a[i]<val) num++; return num; } inline int BL_find_more(int x,int y,int val) { int num=0; for(re int i=x;i<=y;i++) if(!vis[i]&&a[i]>val) num++; return num; } inline int find_less(int x,int y,int val) { int num=0; for(re int i=1;i<=tot;i++) { if(x>l[i]&&y<r[i]) return BL_find_less(x,y,val); if(x<=l[i]&&y>=r[i]) num+=B_ask(i,val); else if(x<=l[i]&&y<r[i]) num+=BL_find_less(l[i],y,val); else if(y>=r[i]&&x>l[i]) num+=BL_find_less(x,r[i],val); } return num; } inline int find_more(int x,int y,int val) { int num=0; for(re int i=1;i<=tot;i++) { if(x>l[i]&&y<r[i]) return BL_find_more(x,y,val); if(x<=l[i]&&y>=r[i]) num+=B_ask(i,n)-B_ask(i,val); else if(x<=l[i]&&y<r[i]) num+=BL_find_more(l[i],y,val); else if(y>=r[i]&&x>l[i]) num+=BL_find_more(x,r[i],val); } return num; } int main() { n=read(),m=read(); for(re int i=1;i<=n;i++) a[i]=read(),to[a[i]]=i; get_pair(),build_block(); int x; while(m--) { printf("%lld\n",ans); x=read(); if(to[x]!=1) ans-=find_more(1,to[x]-1,x); if(to[x]!=n) ans-=find_less(to[x]+1,n,x); BL_change(x); } return 0; }