国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

BZOJ 3295: [Cqoi2011]動態逆序對

2019-11-08 20:05:23
字體:
來源:轉載
供稿:網友

首先反個順序,把刪除當做從末尾插入。

計算每個數剛被插入的時候原數列對其逆序對的貢獻,使用cdq分治,先把[l,r]序列按在原數組中的位置pos排序,然后使用權值BIT維護,就能維護出左半邊的數對右半邊的數的貢獻(正反兩遍)。

最后輸出答案的時候累加一遍即可

對于初始沒被刪除的,只需要預先計算一遍他們對所有被刪除了的數的逆序對的貢獻就可以了,順便統計出執行完刪除操作之后的逆序對數。

//QWsin#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=100000+10;typedef long long ll;int n,m,num[maxn],pos[maxn];int C[maxn];inline void clearbit(){memset(C,0,sizeof C);}#define lowbit(i) ((i)&-(i))inline void updata(int pos,int val){ for(int i=pos;i<=n;i+=lowbit(i)) C[i]+=val; }inline int query(int pos){ int ret=0; for(int i=pos;i;i-=lowbit(i)) ret+=C[i]; return ret;}int vis[maxn],op[maxn];//vis=1 表示在某個刪除操作中 //op[i] 表示i這個數字最開始對應的OP編號 struct OP{ int x,id,ans,t; inline void input(int i){ scanf("%d",&x);id=i;vis[x]=1;ans=0;op[x]=i; } inline bool Operator < (const OP &rhs)const{ return pos[x]<pos[rhs.x]; }}a[maxn],t[maxn];ll ans[maxn];void solve(int l,int r){ if(l==r) return ; int mid=(l+r)>>1; solve(l,mid); solve(mid+1,r); for(int i=l;i<=r;++i) t[i]=a[i],t[i].t=(i>mid); sort(t+l,t+r+1); for(int i=l;i<=r;++i) if(t[i].t==0) updata(t[i].x,1); else ans[t[i].id]+=query(n)-query(t[i].x); for(int i=l;i<=r;++i) if(t[i].t==0) updata(t[i].x,-1); for(int i=r;i>=l;--i) if(t[i].t==0) updata(t[i].x,1); else ans[t[i].id]+=query(t[i].x); for(int i=r;i>=l;--i) if(t[i].t==0) updata(t[i].x,-1);}int main(){ freopen("std.in","r",stdin); cin>>n>>m; for(int i=1;i<=n;++i) scanf("%d",num+i),pos[num[i]]=i; for(int i=1;i<=m;++i) a[m+1-i].input(m+1-i); ll sum=0; for(int i=1;i<=n;++i) if(!vis[num[i]]) { sum+=query(n)-query(num[i]); updata(num[i],1); } else { int t=query(n)-query(num[i]); ans[a[op[num[i]]].id]+=t; } clearbit(); for(int i=n;i>=1;--i) if(!vis[num[i]]) {// sum+=query(num[i]);//一開始你還把原序列的逆序對算成了二倍(扶額) updata(num[i],1); } else { int t=query(num[i]); ans[a[op[num[i]]].id]+=t; } clearbit(); solve(1,m); ans[0]=sum; for(int i=1;i<=m;++i) ans[i]+=ans[i-1]; for(int i=m;i>=1;--i)
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 罗源县| 顺义区| 锡林浩特市| 通辽市| 青神县| 乌鲁木齐市| 包头市| 塔河县| 新竹市| 汉寿县| 庐江县| 乌兰浩特市| 安仁县| 佳木斯市| 定日县| 山丹县| 革吉县| 小金县| 会同县| 扶沟县| 太和县| 涟水县| 中牟县| 尚志市| 陕西省| 邵武市| 福贡县| 依兰县| 冀州市| 萍乡市| 巩义市| 赣榆县| 杂多县| 垣曲县| 和平区| 白银市| 汨罗市| 通辽市| 徐汇区| 鄢陵县| 合川市|