线段树菜鸟一题+归并排序【求逆序数】POJ2299
题目链接:http://poj.org/problem?id=2299
归并排序解法链接:http://blog.csdn.net/lyy289065406/article/details/6647346
然后是自己写的线段树:
注意点在代码中。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r//2. 这一块的l,1分清楚 const int maxn=500005; struct M { int x; int id; }m[maxn]; int b[maxn]; struct Tree { int l,r,sum; }tree[maxn*4];// 1.此处的结点maxn*4? 开maxn*2会RE int cmp(struct M a,struct M b) { return a.x<b.x; } void Pushup(int rt) { tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void build(int rt,int l,int r) { if(l==r) {tree[rt].sum=0;return;} else { int m=(l+r)>>1; build(lson); build(rson); } Pushup(rt); //tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void update(int p,int add,int rt,int l,int r) { if(p>r) return; if(l==r) { tree[rt].sum+=add; return; } else { int m=(l+r)>>1; if(p<=m) update(p,add,lson);//3. 要p的作用哪。只更新一半 。因为下面有Pushup else update(p,add,rson); } Pushup(rt); } int query(int a,int b,int rt,int l,int r) { int ans=0; if(a<=l&&b>=r) { return tree[rt].sum; } else { int m=(l+r)>>1; if(a<=m) ans+=query(a,b,lson); if(b>m) //4. 这地方是r>m果断而不是r>=m ans+=query(a,b,rson); } return ans; } int main() { int n; while(scanf("%d",&n)!=EOF) { if(!n) break; for(int i=1;i<=n;i++) { scanf("%d",&m[i].x); m[i].id=i; } sort(m+1,m+1+n,cmp); //离散化 b[m[1].id]=1; for(int i=2;i<=n;i++) { if(m[i].x==m[i-1].x) b[m[i].id]=b[m[i-1].id]; else b[m[i].id]=i; } build(1,1,n); long long ans=0; for(int i=1;i<=n;i++) { ans+=query(b[i]+1,n,1,1,n); update(b[i],1,1,1,n); } printf("%lld\n",ans); } return 0; } //还有不懂的时候调试一下,出现奇怪的地方一般是自己错了。 或者模板敲错。