Ultra-QuickSort
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
Ultra-QuickSort produces the output
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.InputThe input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.OutputFor every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.Sample Input
5
9
1
0
5
4
3
1
2
3
0
Sample Output
6 0
思路:对于每次输入的数据,即刻判断其前面比它大的数的个数,范围是当前这个数+1,到最大值,然后立刻更新。因为数据很大,需要离散化,具体看代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e6;
struct node{
int l;
int r;
int sum;
}e[maxn<<2];
struct tree{
int pos;
}tree[maxn<<2];
long long sum;
int mp[maxn];
int a[maxn],n;
void build(int l,int r,int cur)
{
e[cur].l=l;
e[cur].r=r;
e[cur].sum=0;
if(l==r)
return;
int mid=(l+r)/2;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
}
void pushup(int cur)
{
e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
}
int query(int pl,int pr,int cur)
{
if(pl<=e[cur].l&&e[cur].r<=pr)
{
return e[cur].sum;
}
int mid=(e[cur].l+e[cur].r)/2;
int res=0;
if(pl<=mid)
res+=query(pl,pr,cur<<1);
if(pr>mid)
res+=query(pl,pr,cur<<1|1);
return res;
}
void update(int tar,int cur)
{
if(e[cur].l==e[cur].r)
{
e[cur].sum++;
return;
}
int mid=(e[cur].l+e[cur].r)/2;
if(tar<=mid)
update(tar,cur<<1);
else
update(tar,cur<<1|1);
pushup(cur);
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(mp,0,sizeof(mp));
memset(a,0,sizeof(a));
sum=0;
build(1,maxn,1);
int t=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
mp[++t]=a[i];
}
sort(mp+1,mp+t+1);
int cnt=1;
int R;
for(int i=2;i<=t;i++)
{
if(mp[i]!=mp[i-1])
{
mp[++cnt]=mp[i];
}
}
for(int i=1;i<=n;i++)
{
int ul=lower_bound(mp+1,mp+1+cnt,a[i])-mp;
tree[i].pos=ul;
// cout<<ul<<endl;
}
for(int i=1;i<=n;i++)
{
sum+=query(tree[i].pos+1,maxn,1);
update(tree[i].pos,1);
}
printf("%lld
",sum);
}
}
Minimum Inversion Number
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
InputThe input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
OutputFor each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16
题意:将一组数循环后移,问逆序数的最少为多少
题解:1、对于某一序列,其中的某一个数a[i]能构成多少个逆序,只须判断在a[i]+1~n的范围内找之前的数是否出现过的次数; 2、然后求出第一个序列的逆序数。 3、由第一个序列的逆序数可以推出它下一个序列的逆序数。 有规律 下一个序列的逆序数 sum = 上一个的sum - a[i] - 1- a[i];如果得出呢 比如说: 序列 3 6 9 0 8 5 7 4 2 1 把3移到后面,则它的逆序数会减少3个(0 2 1) 但同时会增加 n - a[i] - 1个。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define inf 99999999999
6 using namespace std;
7 const int maxn=5010;
8 typedef long long ll;
9 int n;
10 struct node{
11 int l;
12 int r;
13 int sum;
14 }e[maxn<<2];
15 int a[maxn<<2];
16 void build(int l,int r,int cur)
17 {
18 e[cur].l=l;
19 e[cur].r=r;
20 e[cur].sum=0;
21 if(l==r)
22 return;
23 int mid=(l+r)/2;
24 build(l,mid,cur<<1);
25 build(mid+1,r,cur<<1|1);
26 }
27 ll query(int pl,int pr,int cur)
28 {
29 if(pl<=e[cur].l&&e[cur].r<=pr)
30 {
31 return e[cur].sum;
32 }
33 ll res=0;
34 int mid=(e[cur].l+e[cur].r)/2;
35 if(pl<=mid)
36 res+=query(pl,pr,cur<<1);
37 if(pr>mid)
38 res+=query(pl,pr,cur<<1|1);
39 return res;
40 }
41 void update(int tar,int cur)
42 {
43 if(e[cur].l==e[cur].r)
44 {
45 e[cur].sum++;
46 return ;
47 }
48 int mid=(e[cur].l+e[cur].r)/2;
49 if(tar<=mid)
50 update(tar,cur<<1);
51 else
52 update(tar,cur<<1|1);
53 e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
54 }
55 int main()
56 {
57 while(~scanf("%d",&n))
58 {
59 int t=n;
60 ll res=0;build(0,n,1);
61 memset(a,0,sizeof(a));
62 for(int i=0;i<n;i++)
63 {
64 scanf("%d",&a[i]);
65 res+=query(a[i]+1,n,1);
66 update(a[i],1);
67 }
68 int k=0;
69 ll ans=inf;
70 ans=res;
71 for(int i=0;i<n;++i) {
72 res=res-a[i]+(n-1-a[i]);
73 ans=min(ans,res);
74 }
75 printf("%lld
",ans);
76 }
77
78 }
问题 D: 积木
时间限制: 1 Sec 内存限制: 128 MB题目描述
有n个积木,第i个积木的高度为a[i],求每个积木前面有几个比它矮的积木
输入
//(1<=n<=100000)(1<=a[i]<=1000000000)
输出
样例输入
5
1 2 3 4 5
样例输出
0 1 2 3 4
注意:多组输入~~~~~~~
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 typedef long long ll;
7 const int maxn=1e5+10;
8 struct node{
9 ll l;
10 ll r;
11 long long sum;
12 }e[maxn<<2];
13 long long ans[maxn<<2];
14 struct tree{
15 ll pos;
16 }tree[maxn<<2];
17 long long sum;
18 long long mp[maxn];
19 long long a[maxn],n;
20 void build(ll l,ll r,ll cur)
21 {
22 e[cur].l=l;
23 e[cur].r=r;
24 e[cur].sum=0;
25 if(l==r)
26 return;
27 ll mid=(l+r)/2;
28 build(l,mid,cur<<1);
29 build(mid+1,r,cur<<1|1);
30 }
31 void pushup(ll cur)
32 {
33 e[cur].sum=e[cur<<1].sum+e[cur<<1|1].sum;
34 }
35 ll query(ll pl,ll pr,ll cur)
36 {
37 if(pl<=e[cur].l&&e[cur].r<=pr)
38 {
39 return e[cur].sum;
40 }
41 ll mid=(e[cur].l+e[cur].r)/2;
42 ll res=0;
43 if(pl<=mid)
44 res+=query(pl,pr,cur<<1);
45 if(pr>mid)
46 res+=query(pl,pr,cur<<1|1);
47 return res;
48 }
49 void update(long long tar,ll cur)
50 {
51 if(e[cur].l==e[cur].r)
52 {
53 e[cur].sum++;
54 return;
55 }
56 ll mid=(e[cur].l+e[cur].r)/2;
57 if(tar<=mid)
58 update(tar,cur<<1);
59 else
60 update(tar,cur<<1|1);
61 pushup(cur);
62 }
63 int main()
64 {
65 while(~scanf("%lld",&n))
66 {
67 sum=0;
68 build(1,maxn,1);
69 ll t=0;
70 for(ll i=1;i<=n;i++)
71 {
72 scanf("%lld",&a[i]);
73 mp[++t]=a[i];
74 }
75 sort(mp+1,mp+t+1);
76 ll cnt=1;
77 ll R;
78
79 for(ll i=2;i<=t;i++)
80 {
81 if(mp[i]!=mp[i-1])
82 {
83 mp[++cnt]=mp[i];
84 }
85 }
86 for(ll i=1;i<=n;i++)
87 {
88 ll ul=lower_bound(mp+1,mp+1+cnt,a[i])-mp;
89 tree[i].pos=ul;
90 // cout<<ul<<endl;
91 }
92 for(ll i=1;i<=n;i++)
93 {
94 sum+=query(1,tree[i].pos-1,1);
95 ans[i]=sum;
96 //printf("%lld ",sum);
97 update(tree[i].pos,1);
98 }
99 for(ll i=1;i<n;i++)
100 {
101 printf("%lld ",ans[i]-ans[i-1]);
102 }
103 printf("%lld
",ans[n]-ans[n-1]);
104
105 // printf("%lld
",sum);
106 }
107
108 }