18.11.28 内排序四则

求逆序对数(10分)

题目内容:

对于一个长度为N的整数序列A,满足i < j 且 Ai > Aj.的数对(i,j)称为整数序列A的一个逆序
<j<=n且ai><j<=n且ai><j<=n且ai><j<=n且ai>

请求出整数序列A的所有逆序对个数

 

输入格式:

输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列

 

输出格式:

每组数据对应一行,输出逆序对的个数

 

输入样例:

5
1 2 3 4 5
5
5 4 3 2 1
1
1
0

 

输出样例:

0
10
0

 

时间限制:200ms内存限制:32000kb
 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10 #include <vector>
11 #include <fstream>
12 #include <set>
13 #define maxn 20005
14 #define inf 999999
15 
16 using namespace std;
17 int n, a[maxn],tmp[maxn];
18 int sum;
19 
20 inline void swap(int x, int y) {
21     int tmp = a[x];
22     a[x] = a[y];
23     a[y] = tmp;
24 }
25 
26 void mysort(int left,int right){
27     if (left >= right)return;
28     int mid = (left + right) / 2;
29     mysort(left, mid);
30     mysort(mid + 1, right);
31     int p1 = left, p2 = mid+1,i=left;
32     while (p1<=mid&&p2<=right) {
33         if (a[p1] <= a[p2])
34             tmp[i++] = a[p1++];
35         else if (a[p2] < a[p1])
36         {
37             tmp[i++] = a[p2++];
38             sum += mid - p1 + 1;
39         }
40     }
41     while (p2 <= right)
42         tmp[i++] = a[p2++];
43     while (p1 <= mid)
44         tmp[i++] = a[p1++];
45     for (int i = left; i <= right; i++)a[i] = tmp[i];
46 }
47 
48 void init() {
49     while (scanf("%d", &n) != EOF&&n) {
50         sum = 0;
51         for (int i = 1; i <= n; i++)
52             scanf("%d", &a[i]);
53         mysort(1,n);
54         printf("%d\n", sum);
55     }
56 }
57 
58 int main()
59 {
60     init();
61     return 0;
62 }
View Code

超级快排(10分)

题目内容:

在这个问题中,你需要分析特别的算法。这个算法通过对一个包含n个元素的进行操作,一直交换相邻的两个序列的元素直到整个序列呈升序排列。对于输入序列9 1 0 5 4 ,Ultra-QuickSort最终得到的输出为0 1 4 5 9 .你的任务就是来计算出Ultra-QuickSort 至少需要多少swap操作来最终达到对一个给定的输入序列排好序的目标。

 

输入格式:

输入包括多组测试数据。每组测试数据以一行包括一个单独的整数n开始(n<500,000,是输入序列的长度)。每组测试数据接下来的n行包括一个单独的整数a[i],a[i]≤ 999,999,999,代表输入序列第n个元素。输入以一个长度n为0的序列终止。这个序列不应该被处理。

 

输出格式:

对于每组测试数据,你的程序应该输入单独的一行,包括一个整数op,代表对该输入序列进行排序所需要最小的交换次数。

 

输入样例:

 

5
9
1
0
5
4
3
1
2
3
0

输出样例:

6
0

 

时间限制:200ms内存限制:32000kb
 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10 #include <vector>
11 #include <fstream>
12 #include <set>
13 #define maxn 20005
14 #define inf 999999
15 
16 using namespace std;
17 int n, a[maxn],tmp[maxn];
18 int sum;
19 
20 inline void swap(int x, int y) {
21     int tmp = a[x];
22     a[x] = a[y];
23     a[y] = tmp;
24 }
25 
26 void mysort(int left,int right){
27     if (left >= right)return;
28     int mid = (left + right) / 2;
29     mysort(left, mid);
30     mysort(mid + 1, right);
31     int p1 = left, p2 = mid+1,i=left;
32     while (p1<=mid&&p2<=right) {
33         if (a[p1] <= a[p2])
34             tmp[i++] = a[p1++];
35         else if (a[p2] < a[p1])
36         {
37             tmp[i++] = a[p2++];
38             sum += mid - p1 + 1;
39         }
40     }
41     while (p2 <= right)
42         tmp[i++] = a[p2++];
43     while (p1 <= mid)
44         tmp[i++] = a[p1++];
45     for (int i = left; i <= right; i++)a[i] = tmp[i];
46 }
47 
48 void init() {
49     while (scanf("%d", &n) != EOF&&n) {
50         sum = 0;
51         for (int i = 1; i <= n; i++)
52             scanf("%d", &a[i]);
53         mysort(1,n);
54         printf("%d\n", sum);
55     }
56 }
57 
58 int main()
59 {
60     init();
61     return 0;
62 }
View Code

Sequence(10分)

题目内容:

给定m个数字序列,每个序列包含n个非负整数。我们从每一个序列中选取一个数字组成一个新的序列,显然一共可以构造出n^m个新序列。接下来我们对每一个新的序列中的数字进行求和,一共会得到n^m个和,请找出最小的n个和

 

输入格式:

输入的第一行是一个整数T,表示测试用例的数量,接下来是T个测试用例的输入
每个测试用例输入的第一行是两个正整数m(0 < m <= 100)和n(0 < n <= 2000),然后有m行,每行有n个数,数字之间用空格分开,表示这m个序列
序列中的数字不会大于10000

 

输出格式:

对每组测试用例,输出一行用空格隔开的数,表示最小的n个和

 

输入样例:

1
2 3
1 2 3
2 2 3

 

输出样例:

3 3 4

 

时间限制:100ms内存限制:32000kb
  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stack>
  5 #include <string>
  6 #include <math.h>
  7 #include <queue>
  8 #include <stdio.h>
  9 #include <string.h>
 10 #include <vector>
 11 #include <fstream>
 12 #include <set>
 13 #define maxn 2005
 14 #define inf 999999
 15 
 16 using namespace std;
 17 int n, m;
 18 struct maxheap {
 19     int num[maxn];
 20     int cursize;
 21     maxheap() {
 22         memset(num, 0, sizeof(num));
 23         cursize = 0;
 24     }
 25     void siftdown(int p) {
 26         int i = p;
 27         int j = 2 * p;
 28         int val = num[p];
 29         while (j <= cursize) {
 30             if (j <= cursize - 1 && num[j + 1] > num[j])
 31                 j++;
 32             if (num[j] > val)
 33             {
 34                 num[i] = num[j];
 35                 i = j; j = 2 * j;
 36             }
 37             else break;
 38         }
 39         num[i] = val;
 40     }
 41     void siftup(int p) {
 42         int i = p;
 43         int val = num[i];
 44         while (i > 1 && num[i / 2] < val) {
 45             num[i] = num[i / 2];
 46             i = i/2;
 47         }
 48         num[i] = val;
 49     }
 50     void makeheap(int*a) {
 51         cursize = n;
 52         for (int i = 1; i <= n; i++)
 53             num[i] = a[i];
 54         for (int i = n / 2; i >= 0; i--)
 55             siftdown(i);
 56     }
 57     void add(int x) {
 58         if (cursize == n)
 59         {
 60             num[1] = x;
 61             siftdown(1);
 62         }
 63         else
 64         {
 65             num[++cursize] = x;
 66             siftup(cursize);
 67         }
 68     }
 69     void removemax() {
 70         num[1] = num[cursize--];
 71         siftdown(1);
 72     }
 73 }all[2];
 74 
 75 void init() {
 76     int kase;
 77     scanf("%d", &kase);
 78     while (kase--) {
 79         scanf("%d%d", &m, &n);
 80         maxheap sum;
 81         int a[maxn], b[maxn];
 82         for (int i = 1; i <= n; i++) 
 83             scanf("%d", &a[i]);
 84         sort(a + 1, a + n + 1);
 85         for (int i = 2; i <= m; i++) {
 86             for (int j = 1; j <= n; j++)
 87                 scanf("%d", &b[j]);
 88             for (int j = 1; j <= n; j++)
 89                 sum.add(a[j] + b[1]);
 90             for (int j = 2; j <= n; j++)
 91                 for (int k = 1; k <= n; k++)
 92                     if (a[k] + b[j] < sum.num[1])
 93                         sum.add(a[k] + b[j]);
 94             for (int j = 1; j <= n; j++) {
 95                 {
 96                     a[n-j+1] = sum.num[1];
 97                     sum.removemax();
 98                 }
 99             }
100         }
101         printf("%d", a[1]);
102         for (int i = 2; i <=n; i++)
103             printf(" %d", a[i]);
104         printf("\n");
105     }
106 }
107 
108 int main()
109 {
110     init();
111     return 0;
112 }
View Code

这道题……堆也是写得很糟心啊

 

促销活动(10分)

 

题目内容:

Great Bytelandish超市联盟想请你编写一个程序模拟计算促销活动的开销

促销活动遵守以下规则:

参加促销活动的客户,可以在消费结束后将自己的消费账单投入一个指定的投票箱里

当一天的促销活动结束时,将从投票箱中选出两份账单:一份是消费金额最大的账单,一份是消费金额最小的账单。最大金额账单对应的客户,将得到一笔奖金,奖金数等于金额最大的账单与金额最小的账单之间的差值。输入保证总可以找到这样的两份账单

为了避免一个消费者重复获奖,抽出的两份账单都不能放回投票箱,但是其他账单还会留在投票箱里继续参加下一天的促销活动

你的任务是根据每天促销活动的信息,计算出超市在整个促销活动期间的奖金开销

 

输入格式:

输入的第一行是一个整数n(1 <= n <= 5000),表示促销活动的天数
接下来有n行输入,每行有若干个非负整数,整数之间用空格分隔
第i+1行的数据代表第i天的账单信息,每行的第一个整数k(0 <= k <= 10^5)表示当天有多少个账单,接下来是k个正整数,对应每份账单的金额,账单金额都不超过10^6
整个促销活动涉及到的账单数之和不超过10^6

 

输出格式:

一个整数,表示超市在整个促销活动中的奖金开销

 

输入样例:

 

5
3 1 2 3
2 1 1
4 10 5 5 1
0
1 2

输出样例:

19
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include<set>
 7 using namespace std;
 8 
 9 int n;
10 multiset<int>q;
11 
12 int main()
13 {
14     scanf("%d", &n);
15     int sum = 0;
16     for (int i = 1; i <= n; i++)
17     {
18         int x;
19         scanf("%d", &x);
20         for (int j = 1; j <= x; j++)
21         {
22             int a;
23             scanf("%d", &a);
24             q.insert(a);
25         }
26         multiset<int>::iterator i1=q.begin(), i2=q.end();
27         i2--;
28         int min = *i1, max = *i2;
29         sum += max - min;
30         q.erase(i1);
31         q.erase(i2);
32     }
33     printf("%d\n", sum);
34     return 0;
35 }
View Code

这道题我到现在都还没改对,所以上面的是STL水过的代码

我本来是想懒惰地复制最小堆改改变成最大堆,没想到死活有个点过不去(又改了一次升级到了2个点……手动微笑)

代码存下放这里

  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stack>
  5 #include <string>
  6 #include <math.h>
  7 #include <queue>
  8 #include <stdio.h>
  9 #include <string.h>
 10 #include <vector>
 11 #include <fstream>
 12 #include <set>
 13 #define maxn 5001
 14 #define inf 999999
 15 
 16 using namespace std;
 17 int day;
 18 struct maxheap {
 19     int num[maxn];
 20     int cursize;
 21     int minp;
 22     int minval;
 23     maxheap() {
 24         memset(num, 0, sizeof(num));
 25         cursize = 0;
 26         minval = inf;
 27     }
 28     int siftdown(int p) {
 29         int i = p;
 30         int j = 2 * p;
 31         int val = num[p];
 32         while (j <= cursize) {
 33             if (j <= cursize - 1 && num[j + 1] > num[j])
 34                 j++;
 35             if (num[j] > val)
 36             {
 37                 num[i] = num[j];
 38                 i = j; j = 2 * j;
 39             }
 40             else break;
 41         }
 42         num[i] = val;
 43         return i;
 44     }
 45     int siftup(int p) {
 46         int i = p;
 47         int val = num[i];
 48         while (i > 1 && num[i / 2] < val) {
 49             if (i / 2 == minp)
 50                 minp = i;
 51             num[i] = num[i / 2];
 52             i = i/2;
 53         }
 54         num[i] = val;
 55         return i;
 56     }
 57     void add(int x) {
 58         if (cursize == day)
 59         {
 60             num[minp] = x;
 61             int i=siftup(minp);
 62             minval = x, minp = i;
 63             for(int i=cursize/2;i<=cursize;i++)
 64                 if (num[i] < minval) {
 65                     minp = i;
 66                     minval = num[i];
 67                 }
 68         }
 69         else
 70         {
 71             num[++cursize] = x;
 72             int i=siftup(cursize);
 73             if (x < minval) {
 74                 minval = x;
 75                 minp = i;
 76             }
 77         }
 78     }
 79     void removemax() {
 80         if (cursize == 1) {
 81             minval = inf;
 82             cursize = 0;
 83         }
 84         else {
 85             num[1] = num[cursize--];
 86             int i = siftdown(1);
 87             if (minp == cursize + 1)
 88                 minp = i;
 89         }
 90     }
 91     void removep(int x) {
 92         if (minval == x)
 93         {
 94             num[minp] = num[cursize--];
 95             minval = num[minp];
 96             for (int i = cursize / 2; i <= cursize; i++)
 97                 if (num[i] < minval) {
 98                     minp = i;
 99                     minval = num[i];
100                 }
101             if (cursize == 0)
102                 minval = inf;
103         }
104     }
105 };
106 struct minheap {
107     int num[maxn];
108     int cursize;
109     int maxp;
110     int maxval;
111     minheap() {
112         memset(num, 0, sizeof(num));
113         cursize = 0;
114         maxval = 0;
115     }
116     int siftdown(int p) {
117         int i = p;
118         int j = 2 * p;
119         int val = num[p];
120         while (j <= cursize) {
121             if (j <= cursize - 1 && num[j + 1] < num[j])
122                 j++;
123             if (num[j] < val)
124             {
125                 num[i] = num[j];
126                 i = j; j = 2 * j;
127             }
128             else break;
129         }
130         num[i] = val;
131         return i;
132     }
133     int siftup(int p) {
134         int i = p;
135         int val = num[i];
136         while (i > 1 && num[i / 2] > val) {
137             if (i / 2 == maxp)
138                 maxp = i;
139             num[i] = num[i / 2];
140             i = i / 2;
141         }
142         num[i] = val;
143         return i;
144     }
145     void add(int x) {
146         if (cursize == day)
147         {
148             num[maxp] = x;
149             int i=siftup(maxp);
150             maxval = x, maxp = i;
151             for(int i=cursize/2;i<=cursize;i++)
152                 if (num[i] > maxval)
153                 {
154                     maxp = i;
155                     maxval = num[i];
156                 }
157         }
158         else
159         {
160             num[++cursize] = x;
161             int i=siftup(cursize);
162             if (x > maxval) {
163                 maxval = x;
164                 maxp = i;
165             }
166         }
167     }
168     void removemax() {
169         if (cursize == 1) {
170             cursize = 0;
171             maxval = 0;
172         }
173         else {
174             num[1] = num[cursize--];
175             int i = siftdown(1);
176             if (maxp == cursize + 1)
177                 maxp = i;
178         }
179     }
180     void removep(int x) {
181         if (maxval == x)
182         {
183             num[maxp] = num[cursize--];
184             maxval = num[maxp];
185             for (int i = cursize / 2; i <= cursize; i++)
186                 if (num[i] < maxval) {
187                     maxp = i;
188                     maxval = num[i];
189                 }
190         }
191     }
192 };
193 
194 void init() {
195     scanf("%d", &day);
196     minheap getmin;
197     maxheap getmax;
198     int sum = 0;
199     int c = 0;
200     for (int i = 1; i <= day; i++) {
201         int n;
202         scanf("%d", &n);
203         c += n;
204         for (int j = 1; j <= n; j++)
205         {
206             int x;
207             scanf("%d", &x);
208             if(x<getmin.maxval||getmin.cursize!=day)
209                 getmin.add(x);
210             if(x>getmax.minval || getmax.cursize != day)
211                 getmax.add(x);
212         }
213         int max = getmax.num[1], min = getmin.num[1];
214         sum += max - min;
215         getmax.removemax();
216         getmin.removemax();
217         if (c <= day)
218         {
219             getmax.removep(min);
220             getmin.removep(max);
221         }
222         c -= 2;
223     }
224     printf("%d\n", sum);
225 }
226 
227 int main()
228 {
229     init();
230     return 0;
231 }
View Code

 

posted @ 2018-11-28 15:04  TobicYAL  阅读(593)  评论(0编辑  收藏  举报