【bzoj2141】 排队 树状数组+主席树
2015-08-07 19:22
176 查看
卧槽,为什么网上没有主席树的题解呀?!!!
貌似分块也可以做,但是代码会长一点吧,真心良心题不卡空间,O(nlog^2n)随便水。
结果发现自己忘考虑相同的数,一开始逆序对数求错了。
貌似分块也可以做,但是代码会长一点吧,真心良心题不卡空间,O(nlog^2n)随便水。
结果发现自己忘考虑相同的数,一开始逆序对数求错了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 8000100 using namespace std; struct yts { int x,id; }a[20010]; int lch[maxn],rch[maxn],cnt[maxn]; int root[20010],c[20010],f[20010],l[30],r[30]; int n,T,tot,mx,ans,llen,rlen; int lowbit(int x) { return x&(-x); } bool cmp(yts a,yts b) { return a.x<b.x; } void add(int i,int x) { while (i<=n) { c[i]+=x; i+=lowbit(i); } } int query(int x) { int ans=0; for (int i=x;i;i-=lowbit(i)) ans+=c[i]; return ans; } int modify(int pre,int l,int r,int x,int f) { int now=++tot; if (l==r) { cnt[now]=cnt[pre]+f;lch[now]=rch[now]=0; } else { int mid=(l+r)/2; if (x<=mid) { rch[now]=rch[pre];lch[now]=modify(lch[pre],l,mid,x,f); } else { lch[now]=lch[pre];rch[now]=modify(rch[pre],mid+1,r,x,f); } cnt[now]=cnt[lch[now]]+cnt[rch[now]]; } return now; } void modify(int x,int t,int f) { for (int i=x;i<=n;i+=lowbit(i)) root[i]=modify(root[i],1,mx,t,f); } int askless(int L,int R,int x) { if (x<L) return 0; if (R<=x) { int sum=0; for (int i=1;i<=llen;i++) sum-=cnt[l[i]]; for (int i=1;i<=rlen;i++) sum+=cnt[r[i]]; return sum; } int mid=(L+R)/2; if (x<=mid) { for (int i=1;i<=llen;i++) l[i]=lch[l[i]]; for (int i=1;i<=rlen;i++) r[i]=lch[r[i]]; return askless(L,mid,x); } else { int sum=0; for (int i=1;i<=llen;i++) sum-=cnt[lch[l[i]]]; for (int i=1;i<=rlen;i++) sum+=cnt[lch[r[i]]]; for (int i=1;i<=llen;i++) l[i]=rch[l[i]]; for (int i=1;i<=rlen;i++) r[i]=rch[r[i]]; return sum+askless(mid+1,R,x); } } int askmore(int L,int R,int x) { if (x>R) return 0; if (x<=L) { int sum=0; for (int i=1;i<=llen;i++) sum-=cnt[l[i]]; for (int i=1;i<=rlen;i++) sum+=cnt[r[i]]; return sum; } int mid=(L+R)/2; if (mid<x) { for (int i=1;i<=llen;i++) l[i]=rch[l[i]]; for (int i=1;i<=rlen;i++) r[i]=rch[r[i]]; return askmore(mid+1,R,x); } else { int sum=0; for (int i=1;i<=llen;i++) sum-=cnt[rch[l[i]]]; for (int i=1;i<=rlen;i++) sum+=cnt[rch[r[i]]]; for (int i=1;i<=llen;i++) l[i]=lch[l[i]]; for (int i=1;i<=rlen;i++) r[i]=lch[r[i]]; return sum+askmore(L,mid,x); } } void mem(int x,int y) { llen=0,rlen=0; for (int i=x;i;i-=lowbit(i)) l[++llen]=root[i]; for (int i=y;i;i-=lowbit(i)) r[++rlen]=root[i]; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i].x); for (int i=1;i<=n;i++) a[i].id=i; sort(a+1,a+n+1,cmp); mx=1;f[a[1].id]=1; for (int i=2;i<=n;i++) { if (a[i].x!=a[i-1].x) mx++; f[a[i].id]=mx; } for (int i=n;i>=1;i--) { ans+=query(f[i]-1); add(f[i],1); } printf("%d\n",ans); tot=0;root[0]=cnt[0]=lch[0]=rch[0]=0; for (int i=1;i<=n;i++) root[i]=root[0]; for (int i=1;i<=n;i++) modify(i,f[i],1); scanf("%d",&T); while (T--) { int x,y; scanf("%d%d",&x,&y); if (x>y) swap(x,y); mem(x,y); ans-=askless(1,mx,f[x]-1); mem(x,y); ans-=askmore(1,mx,f[y]+1); mem(x,y); ans+=askmore(1,mx,f[x]+1); mem(x,y); ans+=askless(1,mx,f[y]-1); printf("%d\n",ans); modify(x,f[x],-1);modify(x,f[y],1); modify(y,f[y],-1);modify(y,f[x],1); swap(f[x],f[y]); } return 0; }
相关文章推荐
- Python简单爬虫
- HDU 5355 Cake(数学 DFS)
- POJ-2136 Vertical Histogram-用*号统计字母个数
- C++(12)STL实践与分析之顺序容器
- Python正则表达式速查表
- hdu 2084 - 数塔(解题报告)
- codeforces Gym 100418D BOPC 打表找规律,求逆元
- java容器类---ArrayList
- 简介BFC
- POJ-1833 排列-字典序
- List,Map的遍历
- 考试排名(一)(结构体专题)
- ANDROID内存优化——大汇总(转)
- 【CODEFORCES】 A. Expression
- poj 1185 炮兵阵地 (状态压缩)
- Period(kmp)
- hdu 5360 Hiking(贪心)
- HDU 1879 继续畅通工程 prim算法 最小生成树
- 上传文件块client实现
- 用百度API实现热(WIFI)、GPS、基站定位