求逆序对数(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
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 }
超级快排(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
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 }
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
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 }
这道题……堆也是写得很糟心啊
促销活动(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 }
这道题我到现在都还没改对,所以上面的是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 }