luogu1975 [國家集訓隊]排隊
阿新 • • 發佈:2018-12-14
註意 amp etc upd 都是 樹狀數組 namespace con lsh
\(L,R\)又在區間兩端
那麽很顯然的
\(ans=ans-(L對區間zz的貢獻②)+(L對區間zz的貢獻①)-(R對區間zz的貢獻①)+(R對區間zz的貢獻②)\)
那區間內的貢獻咋求啊?
定義不是很明確了嗎 就是區間大於x或者小於的個數
\(=>ans-(區間zz內小於L的個數)+(區間zz內大於L的個數)-(區間zz內大於R的個數)+(區間zz內小於R的個數)\)(註意,相等的沒有任何貢獻)
無腦數據結構唄
隨便來個帶修主席樹 (樹狀數組套線段樹)
復雜度\(nlog^{2}n\)
但常數巨大,更新一次ans要詢問8次
思路
序列中
|i | 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
|----|--|--|--|--|--|--|--|--|--|--|
|a[i]| a| b| c| L| d| e| f| R| g| h|
現逆序對為ans,要交換L,R
則\([1,3],[9,10]\)這兩段區間的都不會被他倆影響 (因為L,R和他們相對位置沒變啦)
所以現在我們只需要考慮區間\([4,8]\)就好,其他的不考慮在內
一個數對一個區間產生逆序對的貢獻為
① 前面大於他的數的個數 (在區間前面)
② 後面小於他的數的個數 (在區間後面)
因為\(L,R\)之間的區間3,6是不變的(廢話)
那麽很顯然的
\(ans=ans-(L對區間zz的貢獻②)+(L對區間zz的貢獻①)-(R對區間zz的貢獻①)+(R對區間zz的貢獻②)\)
那區間內的貢獻咋求啊?
定義不是很明確了嗎 就是區間大於x或者小於的個數
\(=>ans-(區間zz內小於L的個數)+(區間zz內大於L的個數)-(區間zz內大於R的個數)+(區間zz內小於R的個數)\)(註意,相等的沒有任何貢獻)
無腦數據結構唄
隨便來個帶修主席樹 (樹狀數組套線段樹)
復雜度\(nlog^{2}n\)
但常數巨大,更新一次ans要詢問8次
錯誤
都是些zz錯誤
n寫成len
特盤忘記輸出ans
代碼
//天蒼蒼,野茫茫,代碼怎麽這麽長 #include <bits/stdc++.h> #define FOR(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int maxn=1e5+7; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int n,m,ans,len,rt[maxn],a[maxn],lsh[maxn],cnt; int thu[maxn]; struct node { int ch[2],siz; }e[maxn*30]; void build(int &now,int old,int l,int r,int k) { now=++cnt; e[now]=e[old]; e[now].siz++; if(l==r) return; int mid=(l+r)>>1; if(k<=mid) build(e[now].ch[0],e[old].ch[0],l,mid,k); else build(e[now].ch[1],e[old].ch[1],mid+1,r,k); } void modify(int &now,int l,int r,int k,int gs) { if(!now) now=++cnt; e[now].siz+=gs; if(l==r) return; int mid=(l+r)>>1; if(k<=mid) modify(e[now].ch[0],l,mid,k,gs); else modify(e[now].ch[1],mid+1,r,k,gs); } int query1(int now,int l,int r,int k) { //小於mid的數 if(l>=k) return 0; if(r<k) { int tot=e[now].siz; FOR(i,1,thu[0]) tot+=e[thu[i]].siz; return tot; } int mid=(l+r)>>1; if(k<=mid) { FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0]; return query1(e[now].ch[0],l,mid,k); } else { int tot=e[e[now].ch[0]].siz; FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[0]].siz; FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1]; return tot+query1(e[now].ch[1],mid+1,r,k); } } int query2(int now,int l,int r,int k) { //大於mid的數 if(r<=k) return 0; if(l>k) { int tot=e[now].siz; FOR(i,1,thu[0]) tot+=e[thu[i]].siz; return tot; } int mid=(l+r)>>1; if(k<=mid) { int tot=e[e[now].ch[1]].siz; FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[1]].siz; FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0]; return tot+query2(e[now].ch[0],l,mid,k); } else { FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1]; return query2(e[now].ch[1],mid+1,r,k); } } int solve(int l,int r,int k,int pd) {//區間內小於(或小於)k的個數 int tmp=0; thu[0]=0; for(int i=r;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n]; tmp+=pd ? query1(rt[r],1,len,k) : query2(rt[r],1,len,k); thu[0]=0; for(int i=l-1;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n]; tmp-=pd ? query1(rt[l-1],1,len,k) : query2(rt[l-1],1,len,k); return tmp; } namespace get_init_ans { int sum[maxn]; void BIT_modify(int x) { for(int i=x;i<=n;i+=(i&-i)) sum[i]++; } int BIT_query(int x) { int tot=0; for(int i=x;i>=1;i-=(i&-i)) tot+=sum[i]; return tot; } void get_ans() { for(int i=1;i<=n;++i) { BIT_modify(a[i]); ans+=i-BIT_query(a[i]); } } } using namespace get_init_ans; int main() { //read n=read(); FOR(i,1,n) a[i]=lsh[i]=read(); //lsh and init sort(lsh+1,lsh+1+n); len=unique(lsh+1,lsh+1+n)-lsh-1; FOR(i,1,n) { a[i]=lower_bound(lsh+1,lsh+1+len,a[i])-lsh; build(rt[i],rt[i-1],1,len,a[i]); } //get_ans get_ans(); cout<<ans<<"\n"; //work m=read(); FOR(i_ak_ioi,1,m) { int x=read(),y=read(),l,l1=0,l2=0,r,r1=0,r2=0; if(a[x]==a[y]) { cout<<ans<<"\n"; continue; } if(x>y) swap(x,y); //query l=x+1,r=y-1; if(l<=r) { l2=solve(l,r,a[x],1); l1=solve(l,r,a[x],0); r2=solve(l,r,a[y],1); r1=solve(l,r,a[y],0); } //update ans=ans-l2+l1-r1+r2+(a[x]<a[y] ? 1 : -1); cout<<ans<<"\n"; //update for(int i=x;i<=n;i+=(i&-i)) { modify(rt[i+n],1,len,a[x],-1); modify(rt[i+n],1,len,a[y],1); } for(int i=y;i<=n;i+=(i&-i)) { modify(rt[i+n],1,len,a[y],-1); modify(rt[i+n],1,len,a[x],1); } swap(a[x],a[y]); } return 0; }
luogu1975 [國家集訓隊]排隊