思路
- 考虑一个严格升序的排列,如果交换两个元素,会一次产生一个或者两个山峰或者山谷,那么他们的数量差不会超过1,并且很显然的,山峰和山谷的数量和要不应该超过n-2
- 考虑构造,要注意到对于不是首尾元素,一次会产生一个山峰一个山谷,对于首端,产生一个山谷,对于尾端,产生一个山峰
那么分三种情况,如果山峰和山谷数量相当,跳过首尾端翻转就行
山峰比较多,选择把尾端的翻转 ,然后向前翻转就行。山谷多同理
#includeC 题目#define yes puts("yes"); #define inf 0x3f3f3f3f #define ll long long #define linf 0x3f3f3f3f3f3f3f3f #define debug(x) cout<<"> "<< x< PII; const int N =10 + 2e5 ,mod=1e9 + 7; int a,b,n; void solve() { cin >> n >> a >> b; if(abs(a - b) > 1 || a + b > n - 2) { cout << "-1n"; return; } vector aa(n+10); for(int i=1;i<=n;i++) aa[i] = i; int l = 1; if(a < b) l = 1; else if(a == b) l = 2; else l = n - 2 * a + 1; for(int i = 0;i >T; while(T--) solve(); return 0; }
思路n个人进行游戏,有两张地图,每个人在地图1,2中有两个不同的能力值,高的可以打败低的,可以任意安排任意的人在任意一张图进行决斗。最后输出01串,1表示这个人有获胜可能,0表示这个人没有获胜可能。
- 如果先按照a的能力值给人排序,可以获胜的人,在这个次序下一定是连续的。
- 考虑01的边界,我们假设能力值 a i a_i ai的人x是胜败的分界点,那么对于他可以打败的[1,i-1]这些人中在地图2的最大能力值 b j b_j bj的人y,如果y仅可以打败x已经打败过的人,那么他一定是败者,如过y可以打败x没有打败的人z,因为我们假设x是最后一个败者,所以z一定是胜者,那么我们就可以通过先让z打败其他人,在最后把z干掉使得x获胜,与假设矛盾。所以,可以得到结论,y一定也只可以打败x打败之后的人。所以y在第二个图中的能力值的位次一定也是i。
- 所以我们可以先对a排序,找到第二个图能力值的位次和第一个图上的能力值位次相同的人即为分界点。
#include#define yes puts("yes"); #define inf 0x3f3f3f3f #define ll long long #define linf 0x3f3f3f3f3f3f3f3f #define debug(x) cout<<"> "<< x< PII; const int N =10 + 2e5 ,mod=1e9 + 7; struct Node{ int a,b; int idx; }aa[N]; PII d[N]; int n; void solve() { cin >> n; for(int i=1;i<=n;i++){ cin >> aa[i].a; aa[i].idx = i; } for(int i=1;i<=n;i++){ cin >> d[i].first; d[i].second = i; } sort(d+1,d+1+n); for(int i=1;i<=n;i++){ aa[d[i].second].b = i; } sort(aa+1,aa+1+n,[&](Node a,Node b){ return a.a < b.a; }); int mx = 0; int pos = 0; for(int i=1;i res(n+5); for(int i=1;i<=n;i++) res[i] = 1; for(int i=1;i<=pos;i++) res[aa[i].idx] = 0; for(int i=1;i<=n;i++) cout << res[i]; cout << endl; } signed main() { ios::sync_with_stdio();cin.tie();cout.tie(); int T;cin>>T; while(T--) solve(); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)