POJ3067 Japan
树状数组基础
View Code
//11584687 NKHelloWorld 3067 Accepted 2764K 485MS C++ 1186B 2013-05-11 14:37:10 //这道题可能存在重边,K可能很大,需要longlong才能过 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; int n,m,k; ll tree[1100]; struct NODE { int x,y; }node[1000*1000]; bool cmp(NODE n1,NODE n2) { if(n1.x == n2.x) { return n1.y < n2.y; } return n1.x < n2.x; } ll sum(int pos) { ll ret = 0; while(pos > 0) { ret += tree[pos]; pos -= (pos & -pos); } return ret; } void BITinsert(int pos ,int val) { while(pos <= 1000) { tree[pos] += val; pos += (pos & -pos); } } int main() { int T; scanf("%d",&T); for(int TT = 1; TT<=T;TT++) { memset(tree,0,sizeof(tree)); scanf("%d%d%d",&n,&m,&k); for(int i=0;i<k;i++) { scanf("%d%d",&node[i].x,&node[i].y); } sort(node,node+k,cmp); ll ans = 0; for(int i=k-1;i>=0;i--) { if(node[i].y != 1) { ans += sum(node[i].y-1); } BITinsert(node[i].y,1); } printf("Test case %d: %lld\n",TT,ans); } return 0; }
POJ2299 Ultra-QuickSort
离散化+树状数组求逆序数
View Code
//11585027 NKHelloWorld 2299 Accepted 9452K 672MS C++ 1224B 2013-05-11 15:54:12 //离散化+树状数组求逆序数 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; int maxval; int a[510000]; ll c[510000]; ll bit_sum(int pos) { ll ret = 0; while(pos >= 1) { ret += c[pos]; pos -= (pos & -pos); } return ret; } void bit_insert(int pos,int det) { while(pos <= maxval) { c[pos] += det; pos += (pos & -pos); } } struct NODE { int val,pos; }node[510000]; bool cmp(NODE a,NODE b) { return a.val < b.val; } int main() { int n; while(scanf("%d",&n), n!=0) { memset(c,0,sizeof(c)); maxval = n; for(int i=1;i<=n;i++) { scanf("%d",&node[i].val); node[i].pos = i; } sort(node+1,node+n+1,cmp); for(int i=1;i<=n;i++) { a[node[i].pos] = i; } //for(int i=1;i<=n;i++)printf("%d ",a[i]);printf("\n"); ll ans = 0; for(int i=n;i>=1;i--) { //printf("i:%d %d\n",i,bit_sum(a[i])); ans += bit_sum(a[i]); bit_insert(a[i],1); } printf("%lld\n",ans); } }
归并排序求逆序
View Code
//11585216 NKHelloWorld 2299 Accepted 3688K 375MS C++ 921B 2013-05-11 16:28:45 //归并排序法求逆序数 //加输入外挂后C++600ms,g++157ms #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; int a[510000]; int t[510000]; ll merge_sort(int l,int r) { ll ans = 0; int i,j,p=l,m=(l+r)/2; if(l==r) return 0; ans += merge_sort(l,m); ans += merge_sort(m+1,r); for(i=l,j=m+1; i<=m && j<= r;) { if(a[i] > a[j]) { t[p++] = a[j++]; ans += m - i + 1; } else { t[p++] = a[i++]; } } while(i <= m) t[p++] = a[i++]; while(j <= r) t[p++] = a[j++]; for(i=l;i<=r;i++) { a[i] = t[i]; } return ans; } inline void scan(int &n) { char c; //while(c=getchar(),c<'0'||c>'9'); n=0; while(c=getchar(),c<='9'&&c>='0') n=n*10+c-'0'; } int main() { int n; while(scanf("%d",&n), n!=0) { for(int i=0;i<n;i++) { scanf("%d",&a[i]); } ll ans = merge_sort(0,n-1); printf("%lld\n",ans); } }