这次真心是个坑……
一开始把A题题意看错了,上来就敲WA了一次,开始心急,之后B题卡了40多分钟,实在无奈跑去看C,发现水题一道,迅速A了之后瞎搞了一下B题,D题看不懂题意,于是Lock了所有代码跑去hack其他人。
最后只提交了3道。
System Test之后只有A和C通过了,不过靠着各种hack补了600分勉强把B的损失补上,最终排81,顺利紫名。
A题 Little Xor
题目大意:给一个序列,长度不超过100,求任意连续区间异或结果的最大值。
题解:因为最多也就100个数,所以直接N^2暴力即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 int a[105]; int main() { int n, ret = 0; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &a[i]); for(int i = 0; i < n; i++) { int temp = 0; for(int j = i; j < n; j++) { temp ^= a[j]; ret = max(temp, ret); } } printf("%d\n", ret); return 0; }
B题 Unsorting Array
大坑……最后只有200多个人AC……
题目大意:给一个任意序列,交换其中两个不相同的数字的位置,使其是一个无序的序列。一个序列为升序或降序则认为其有序。
如果序列初始为无序,依然需要交换两个不同的数字,如果不可能使其变为无序,输出-1,否则输出交换的两个数的序号。
题解:纯YY,做法仅供参考……
首先判断输出-1的情况:
1.如果序列长度小于等于2,必然为-1
2.如果序列中所有数字相同,必然为-1
3.如果序列长度等于3,并且开头和结尾的数相同,必然为-1
上述3个情况中漏掉情况3的很多,我的ROOM里只有2个人对了……
如果不为-1则必然可以找到两个可以交换的数。
我们取序列正中间的那个数,然后向左找离它最近的,比它大的数a,比它小的数b。
同时,向右找离它最近的,比它大的数c,比它小的数d。
如果左右都能找到比它大的数,那么原序列无序,交换这两个数依然无序。
如果左右都能找到比它小的数,那么原序列无序,交换这两个数依然无序。
其他情况原序列可能有序,那么我只要随便交换一下找到的a、b、c、d中的某一个即可破坏有序。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 vector<int> ori; int main() { int n; scanf("%d", &n); bool can = false; for(int i = 0; i < n; i++) { int a; scanf("%d", &a); ori.push_back(a); if(i > 0 && ori[i] != ori[i-1]) can = true; } if(n == 2)can = false; if(n == 3 && ori[0] == ori[2])can = false; if(!can) puts("-1"); else { int a = INF, b = INF, c = INF, d = INF; for(int i = n / 2; i >= 0; i--) if(ori[i] > ori[n/2] && a == INF) a = i; else if(ori[i] < ori[n/2] && b == INF) b = i; for(int i = n / 2; i < n; i++) if(ori[i] > ori[n/2] && c == INF) c = i; else if(ori[i] < ori[n/2] && d == INF) d = i; int r1, r2; if(a != INF && c != INF && ori[a] != ori[c]) r1 = a, r2 = c; else if(b != INF && d != INF && ori[b] != ori[d]) r1 = b, r2 = d; else r1 = min(min(min(a, b), c), d), r2 = n / 2; printf("%d %d\n", r1 + 1, r2 + 1); } return 0; }
C题 Point on Line
题目大意:X轴上有n个点,给定一个d,要求取三个点其中任意两点间的距离<=d,问共有多少种取法。
题解:很水……
要求任意两点间的距离小于等于d,其实就是要求最左的点和最右的点的距离不超过d。
那么对于任意一个点Ai,如果我们把它作为最左的点,
则我们一定可以找到跟它距离不超过d的最右的点Ar(r >= i),
这样我们可以在r - i个点内随意选两个,共有Cn2种取法。
于是枚举每一个点作为最左的点,把取法求和即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 int a[105000]; int main() { int n, d; scanf("%d%d", &n, &d); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); __int64 ret = 0, k; for(int i = 1; i <= n - 2; i++) { int index = lower_bound(a, a + n, a[i] + d) - a; if(a[index] - a[i] <= d) k = index - i; else if(a[index - 1] - a[i] <= d) k = index - i - 1; ret += (k * (k - 1)) / 2; } printf("%I64d\n", ret); return 0; }
D题 Playing with Permutations
英语拙计……
题目大意:开始你有三个序列
一个长度为n的序列p,其初始值是1、2、3、4、5……n-1、n。
一个长度为n的序列q,其初始值由输入获得。
一个长度为n的序列s,其初始值由输入获得。
接下来你必须执行k步操作,每步操作有两种选择。
1.生成一个新的p,其中newp[i] = p[q[i]]
2.生成一个新的p,其中newp[q[i]] = p[i]
要求你在执行的k-1步操作过程中的任意一步,序列p都不得等于序列s。在执行完第k步操作后,序列p等于序列s。
问这种情况是否可能。
题解:
如果把原文的操作一、二完全看懂的话,很容易就可以看出两个操作是互逆,也就是说如果你对p执行了操作1再执行操作2的话,相当于什么也没做。
知道了这一点就很好处理了。
如果我们执行m1次 操作1 可以使得序列p等于序列s,那么我们先执行(k - m1) / 2次的(操作1、操作2)组合,再执行m1次 操作1 即可。
如果我们执行m2次 操作2 可以使得序列p等于序列s,那么我们先执行(k - m2) / 2次的(操作1、操作2)组合,再执行m2次 操作2 即可。
所以只要求出其中的m1、m2再判断一下k - m1,k - m2是否是偶数就行了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <vector> #include <queue> #include <stack> #include <cmath> #include <map> using namespace std; #define INF 0x73737373 #define EPS 1e-8 #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 int p[105], np[105], q[105], r[105]; bool is_same(int n) { for(int i = 1; i <= n; i++) if(p[i] != r[i]) return false; return true; } void init(int n) { for(int i = 1; i <= n; i++) p[i] = i; } int main() { int n, k; scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) scanf("%d", &q[i]); for(int i = 1; i <= n; i++) scanf("%d", &r[i]); init(n); if(is_same(n))puts("NO"); else { int head = -1, tail = -1; for(int i = 1; i <= k; i++) { for(int j = 1; j <= n; j++) np[j] = p[q[j]]; memcpy(p, np, sizeof(p)); if(is_same(n)) { head = i; break; } } init(n); for(int i = 1; i <= k; i++) { for(int j = 1; j <= n; j++) np[q[j]] = p[j]; memcpy(p, np, sizeof(p)); if(is_same(n)) { tail = i; break; } } if(head == -1 && tail == -1) puts("NO"); else if(head == 1 && tail == 1 && k != 1) puts("NO"); else if(head != -1 && (k - head) % 2 == 0) puts("YES"); else if(tail != -1 && (k - tail) % 2 == 0) puts("YES"); else puts("NO"); } return 0; }