-
CF1574C Slay the Dragon
添加链接描述
排序后,用二分找大于等于x的第一个数,然后分情况讨论。- 找到的数大于等于x:
(1)那就要判断是用大于等于x的第一个数还是小于x的第一个数,因为有可能出现大的那个数很大然后有很多浪费的,而剩余数的和又比y小很多,所以要两个数的花费取最小值。
(2) 如果找到的数是第一个数,没有必它小的了,那么只能用第一个数了。 - 找到的数小于x
这也只有一种情况。直接算结果即可。
注意点:
1. 要开longlong
2. 小技巧:ans = max(0ll, y - (sum - a[f]));//小技巧,小于0就不要#include<bits/stdc++.h> #define int long long using namespace std; const int N = 2e5 + 10; int a[N]; signed main() { int n, sum = 0; cin >> n; for (int i = 1; i <= n; i ++ ) { scanf("%lld", &a[i]); sum += a[i]; } sort(a + 1, a + 1 + n); int q; cin >> q; while (q -- ) { int ans = 9999999999999999; int x, y; scanf("%lld%lld", &x, &y); int f = lower_bound(a + 1, a + 1 + n, x) - a; // cout << f << endl; if (a[f] >= x) { if (f != 1)//不是第一个比较选大的或者选小的结果 { ans = min(x - a[f - 1] + max(0ll, y -(sum - a[f- 1])), max(x - a[f], 0ll) + max(0ll, y -(sum - a[f]))); cout << ans << endl; } else //是第一个,只能选这一个 { ans = max(0ll, y - (sum - a[f]));//小技巧,小于0就不要 cout << ans << endl; } } else { f --; ans = x - a[f] + max(0ll, y - (sum - a[f])); cout << ans << endl; } } return 0; }
- 找到的数大于等于x:
-
CF1573B Swaps
原题链接-
暴力思路:
要想使a的字典序小于b就要使a的第一个数字小于b
枚举a中的每一个数,并找到b中的第一个大于的数,算出移到最前面一共需要几步,取最小值。 -
优化思路:
开一个数组存i这个奇数在b数组中的第一个大于i的偶数的下标
然后再枚举一遍a,取最小值即可 -
注意点:
要用快读快写,要开long long!#include<bits/stdc++.h> #define int long long using namespace std; inline int quick_read() noexcept { int x = 0, f = 1; char ch; while (! isdigit (ch = getchar())) if (ch == '-') f = -f; x = ch - '0'; while (isdigit (ch = getchar())) x = (x << 3) + (x << 1) + ch - '0'; return x * f; } inline void quick_write(int x) { if (x == 0) putchar('0'); else { int a[20] = {0}; int top = 0; while (x) { int temp = x % 10; a[++ top] = temp; x /= 10; } for (int i = top; i >= 1; i --) putchar(a[i] + '0'); } } const int N = 1e6 + 10; int a[N], b[N], pos[N]; signed main() { int t = quick_read(); while (t -- ) { int n; n = quick_read(); int ans = 99999999999; for (int i = 1; i <= n; i ++ ) a[i] = quick_read(); for (int i = 1; i <= n; i ++ ) b[i] = quick_read(); for (int i = 1, j = 1; i <= n * 2; i += 2) { while (b[j] < i) j ++; pos[i] = j; } for (int i = 1; i <= n; i ++ ) { if (i - 1 + pos[a[i]] - 1 < ans) ans = i - 1 + pos[a[i]] - 1; } quick_write(ans); puts(""); } return 0; }
-
-
CF1598C Delete Two Elements
题目链接-
思路:
先求平均数,总和sum,平均数k,因为要使删除的两个数不影响剩下数的平均数,它们的和就是sum / n * 2,也就是说如果sum / n * 2
%2 != 0,就说明此题无解,直接continue;所有数的出现次数用map记录,然后遍历所有数,设x = a[i], y = sum /n * 2 - x;
当x == sum / n * 2时,y为0,这时它们的个数就是 x * (x - 1) (用到了组合计数公式,一串数字有n个,两两相组,一共有 n * (n - 1)种方法),因为遍历到这个数的时候,使用这个数的个数来计算,所以ans加完之后就给它的个数归0,
当x != sum / n * 2时,就用 x * y,因为x个数和y个数一共有这么多种组合方法,算完之后给x,y的个数归0; -
代码
#include<bits/stdc++.h> #define int long long const int N = 2e5 + 10; using namespace std; int a[N]; signed main() { int t; cin >> t; while (t -- ) { int n; cin >> n; int sum = 0; map<int, int> num; for (int i = 1; i <= n; i ++ ) { scanf("%lld", &a[i]); num[a[i]] ++; sum += a[i]; } if (sum * 2 % n != 0) { cout << "0" << endl; continue; } int k = sum * 2 / n; int ans = 0; for (int i = 1; i <= n; i ++ ) { int x = a[i], y = k - x; if (num[x] == 0) continue; if (x == y) { ans += (num[x] * (num[x] - 1) / 2); num[x] = 0; } else { ans += (num[x] * num[y]); num[x] = 0; num[y] = 0; } if (num[x] != 0) num[x] = 0; } cout << ans << endl; } return 0; }
-
-
CF1594C Make Them Equal
原题链接-
思路
最多只有两次操作,n和n - 1,可以使整个字符串都变成C,那么就只用考虑能否只用一次把这个字符串都变成C;
通过for (int i = 2; i <= n; i ++ ) { f = 0; for (int j = i; j <= n; j += i) { if (s[j - 1] != c) { f = 1; break; } } if (f == 0) { cout << 1 << endl << i << endl; return; } }
思路:枚举每一位数和它的倍数,如果这一位它所有的倍数位都是合法的,那么选这一位,因为选了这一位之后可以使所有比这一位小的位数都变得合法(因为所有比这一位数小的都不能被这一位数整除),使比这一位大的数的中不能被这一位整除的所有数都变得合法,那也就是说把所有可能不合法的都变得合法了,那么只用选这一位就行了。
-
代码
#include<bits/stdc++.h> using namespace std; int n; char c; string s; void solve() { bool f = 0; cin >> n; getchar(); cin >> c >> s; for (int i = 0; i < n; i ++ ) { if (s[i] != c) {f = 1; break;} } if (!f) { cout << 0 << endl; return; } for (int i = 2; i <= n; i ++ ) { f = 0; for (int j = i; j <= n; j += i) { if (s[j - 1] != c) { f = 1; break; } } if (f == 0) { cout << 1 << endl << i << endl; return; } } cout << 2 << endl << n << " " << n - 1 << endl; } int main() { int t; cin >> t; int cnt = 0; int sum = 0; while (t -- ) { solve(); } return 0; }
-
-
CF1521B Nastia and a Good Array
原题链接-
思路
想要使他变成每相邻的两个数都互质可以让这个数列变成:minn, minn + 1, minn, minn + 1…,因为没有规定要操作次数最小,所以可以这样进行操作; -
注意点
x, y要分别和a[i]和minn更换,所以换成minn时 x = minn, minn = minn,换成minn + 1时,x = minn + 1, y = minn。 -
核心代码
if (abs(pos - i) % 2 != 0) printf("%d %d %d %d\n", i, pos, minn + 1, minn); else printf("%d %d %d %d\n", i, pos, minn, minn);
-
代码
#include<bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t -- ) { int minn = 0x3f3f3f3f; int pos = -1; int n; cin >> n; int num[n + 5]; for (int i = 1; i <= n; i ++ ) { cin >> num[i]; if (num[i] < minn) { minn = num[i]; pos = i; } } cout << n - 1 << endl; for (int i = 1; i <= n; i ++ ) { if (i == pos) continue; if (abs(pos - i) % 2 != 0) printf("%d %d %d %d\n", i, pos, minn + 1, minn); else printf("%d %d %d %d\n", i, pos, minn, minn); } } return 0; }
-
-
CF1562C Rings
原题链接- 思路(只需要满足一个能被另一个整除)
① 如果有大于 n/2 的全是0的字串,那么再随便找一个n / 2的字串即可。(100000,1000,0000)
② 如果遇到一个 0 ,如果这个位置i <= n / 2,那么就是这个位置做开头 i, n,i + 1,n;(101000,01000,1000)
③ 如果遇到一个 0,如果这个位置 i > n / 2,那么就是这个位置做结尾,1,i,1,i - 1 (如果是大于等于n/2,然后结尾是i + 1就有可能越界)(111110,11111,111110)
④ 如果一个0 都没有,就找两个相等的长度为n - 1的字串,这样也能满足被整除的要求,1,n-1,2,n;(1111111,111111,111111); - 代码
#include<bits/stdc++.h> using namespace std; const int N = 2e4 + 10; char s[N]; int main() { int t; cin >> t; while (t -- ) { int n; scanf("%d%s", &n, s + 1); bool f = 0; for (int i = 1; i <= n; i ++ ) { if (s[i] == '0') { f = 1; if (i <= n / 2) printf("%d %d %d %d\n", i, n, i + 1, n); else printf("1 %d 1 %d\n", i, i - 1); break; } } //需要长度相同,才能一样 if (!f) printf("1 %d 2 %d\n", n - 1, n ); } return 0; }
- 思路(只需要满足一个能被另一个整除)
-
CF1556B Take Your Places!
原题链接-
思路
一 一枚举即可,注意一些细节。
记录下原数组中所有奇数的位置和所有偶数的位置,然后和算出所有奇数和偶数距离它们应该所在的位置的距离。
细节:
① 当n为偶数时,枚举所有奇数在奇数位,所有奇数在偶数位,所有偶数在奇数位,所有偶数在偶数位。
② 当n为奇数时,奇数位只能是多的那种数,那就特判一下哪个多,就计算一下那个数放到那一位的步数
③比较最小值即可。 -
代码
#include<bits/stdc++.h> #define int long long using namespace std; signed main() { int t; cin >> t; while (t -- ) { int n; scanf("%lld", &n); int a[n + 10]; int aa = 0, b = 0; int ji[n + 10], ou[n + 10]; for (int i = 1; i <= n; i ++ ) { scanf("%lld", &a[i]); if (a[i] % 2 == 0) { ou[aa ++] = i; } if (a[i] % 2 != 0) { ji[b ++] = i; } } if (abs(aa - b) > 1) { printf("-1\n"); continue; } int ans = 0x3f3f3f3f3f3f3f3f; int sum = 0; //n是偶数时有两种情况 if (n % 2 == 0) { //把所有偶数放在偶数位上 int cnt = 2; sum = 0; for (int i = 0; i < aa; i ++ ) { sum = sum + abs(cnt - ou[i]); cnt += 2; } ans = min (ans, sum); //把所有偶数放在奇数位上 cnt = 1, sum = 0; for (int i = 0; i < aa; i ++ ) { sum = sum + abs(cnt - ou[i]); cnt += 2; } ans = min (ans, sum); //把奇数放在奇数位上 cnt = 1, sum = 0; for (int i = 0; i < b; i ++ ) { sum = sum + abs(cnt - ji[i]); cnt += 2; } ans = min (ans, sum); //把奇数放在偶数位上 cnt = 2, sum = 0; for (int i = 0; i < b; i ++ ) { sum = sum + abs(cnt - ji[i]); cnt += 2; } ans = min (ans, sum); } else //是奇数时只能把个数多的放在奇数位上 { sum = 0; if (aa < b) //奇数多 { //把偶数放到偶数位 int cnt = 2, sum = 0; for (int i = 0; i < aa; i ++ ) { sum = sum + abs(cnt - ou[i]); cnt += 2; } ans = min (ans, sum); //把奇数放到奇数位 cnt = 1, sum = 0; for (int i = 0; i < b; i ++ ) { sum = sum + abs(cnt - ji[i]); cnt += 2; } ans = min (ans, sum); } else //偶数多 { //把偶数放到奇数位 sum = 0; int cnt = 1; for (int i = 0; i < aa; i ++ ) { sum = sum + abs(cnt - ou[i]); cnt += 2; } ans = min (ans, sum); //把奇数放到偶数位 sum = 0; cnt = 2; for (int i = 0; i < b; i ++ ) { sum = sum + abs(cnt - ji[i]); cnt += 2; } ans = min (ans, sum); } } printf("%lld\n", ans); } return 0; }
-
-
CF1538C Number of Pairs
原题链接-
思路
要找两个和在l和r范围内的数,那就先排序,然后枚举每个数a[i],然后找在a[i + 1]到a[n]之间有几个数在l - a[i] 和 r - a[i]之间,然后就是通过二分来查找范围内的数。 -
注意点(二分用法)
lower_bound (a + 1, a + 1 + n,x) - a,找大于等于x的第一个数的下标。
upper_bound (a + 1, a + 1 + n,x) - a,找大于x的第一个数的下标。
如果数组中最大的数也小于x,那么返回的下标会是n + 1。
所以找左范围的时候,其实要找的数是小于等于x的最后一个数,用upper找,找到的数是原本要找的那个数的下标+1,
我们要求的是l - r之间有几个数,照原本的思路来看,用大于等于l的第一个数的下标 - 小于等于r的最后一个数,最终结果是 要+1的,但是实际上用upper找到的是r + 1,所以直接用r - l即可。
主要考察二分函数的用法,代码中附带了二分函数测试器。 -
代码
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 2e5 + 10; int a[N]; int b[N]; signed main() { int T; cin >> T; while (T -- ) { int ans = 0; int n, l, r; scanf("%lld%lld%lld", &n, &l, &r); for (int i = 1; i <= n; i ++ ) scanf("%lld", &a[i]); sort(a + 1, a + 1 + n); for (int i = 1; i <= n; i ++ ) b[i] = a[n - i + 1]; // for (int i = 1; i <= n; i ++ ) cout << a[i] << " "; cout << endl; for (int i = 1; i <= n; i ++ ) { int ll = abs(l - a[i]), rr = abs(r - a[i]); int aa = lower_bound(a + 1 + i, a + 1 + n, ll) - a; int bb = upper_bound(a + 1 + i, a + 1 + n, rr) - a; // printf(" %d %d\n", aa, bb); if (aa > bb) continue; else { ans = ans + (bb - aa); } } cout << ans << endl; } return 0; } //二分函数的运用 //#include<iostream> //#include<cstdio> //#include<cstring> //#include<algorithm> //using namespace std; //int k,n=10; //int a[10]={1,1,1,3,3,5,5,5,5,6}; //int main() //{ // for(int i=0;i<n;i++)cout<<a[i]<<" "; // cout<<endl; // while(scanf("%d",&k)) // { // cout<<k<<"的第一个大于它的位置在"<<((upper_bound(a,a+n,k))-a)+1<<endl; // } //}
-
-
CF1516B AGAGA XOOORRR
原题链接- 异或和满足交换律,就像加法一样
- 任何数异或0不变
- 任何数和自己本身异或等于0
- 思路
- 既然满足交换律,那么顺序不变,从左往右依次异或,如果最终结果为0,那么说明最终数列中有偶数个相等的数的个数
- 如果不是0,说明肯定是奇数个,那么只要从左往右依次异或,看最后那个数出现了几次,只要大于2就都满足要求
- else,就是NO
- 代码
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 2005; int a[N]; signed main() { int t; cin >> t; while (t -- ) { int n; scanf("%lld", &n); int ans = 0; for (int i = 1; i <= n; i ++ ) { scanf("%lld", &a[i]); ans ^= a[i]; } if (ans == 0) //如果最终偶数个相同,那么就直接等于0了 { cout << "YES" << endl; continue; } int ans1 = 0, cnt = 0; for (int i = 1; i <= n; i ++ ) { ans1 = ans1 ^ a[i]; if (ans1 == ans) { cnt ++; ans1 = 0; } } //这便是判奇数,奇数不能使所有的数异或和为0,那么最后剩下的那个数,就是这个数列最终相等的数,那就看看这些相等的数的个数是否大于2 if (ans1 == 0 && cnt >= 2) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
-
CF1520E Arranging The Sheep
原题链接- 思路,通过举例可以推出,最优方案是两边的*向最中间一个靠拢。
- 用a[i]到中间的距离减去中间有几个*。
- 注意特判所有位置都是*,没有*,和只有一个*的情况。
- 代码
#include<bits/stdc++.h> #define int long long using namespace std; signed main() { int t; cin >> t; while (t -- ) { int n; scanf("%lld", &n); string s; cin >> s; int pos[n + 10], cnt = 0; bool f = 0; for (int i = 0; i < n; i ++ ) { if (s[i] == '*') { pos[++cnt] = i + 1; } if (s[i] == '.') f = 1; } if (!f || cnt == 0 || cnt == 1) { cout << "0" << endl; continue; } int ans = 0; int mid = cnt / 2 + 1; for (int i = 1; i <= cnt; i ++ ) { if (i == mid) { continue; } ans = ans + abs(pos[mid] - pos[i]) - abs(mid - i); } printf("%lld\n", ans); } return 0; }
-
CF1519C Berland Regional
-
题意
有n个学生,每个学生属于某所大学,每个学生有一个能力值,n所大学。n次比赛,n次比赛分别是(1 - n人为一队),每所大学都只能自己组队,每k个人一队,最后剩下不足k个人就组不成一队,要求n次比赛所有参赛队伍的总能力值(也就是每所大学除去最后组不成一队的人,其他人的总能力值),还要使能力值尽可能大,也就是说能力值从大到小开始组队。
2. 思路
用二维vector存储每个学校的所有人的能力值,然后排序(从大到小),然后求一下前缀和,然后再用一层双重循环,先枚举每个学校,在枚举一下几个人组成一队,用 n/k*k - 1可以知道k人组队时这个学校有多少人参加,-1是因为数组从0 开始。
3. 代码
```cpp
#include<bits/stdc++.h>
#define int long long int
using namespace std;
const int N = 2e5 + 10;vector<int> g[N]; int s[N]; int id[N]; int ans[N]; bool cmp(int xxx, int yyy) { return xxx > yyy; } signed main() { int t; cin >> t; while (t -- ) { int n; scanf("%lld", &n); for (int i = 1; i <= n; i ++ ) g[i].clear(), ans[i] = 0; for (int i = 1; i <= n; i ++ ) scanf("%lld", &id[i]); for (int i = 1; i <= n; i ++ ) scanf("%lld", &s[i]); for (int i = 1; i <= n; i ++ ) g[id[i]].push_back(s[i]); for (int i = 1; i <= n; i ++ ) { //判断不为空 if (g[i].size() != 0) { sort(g[i].begin(), g[i].end(), cmp);//排序 for (int j = 1; j < g[i].size(); j ++ ) //求前缀 { g[i][j] = g[i][j] + g[i][j - 1]; } } } for (int i = 1; i <= n; i ++ )//求枚举每个大学 { if (g[i].size() != 0)//如果这个大学有人 { int len = g[i].size(); for (int k = 1; k <= len; k ++ ) //枚举分组 { // 加上当前大学的有效人数 ans[k] += g[i][len / k * k - 1]; //该步骤可以实现去掉最后几个不足k人的人,-1是因为数组从0开始 } } } for (int i = 1; i <= n; i ++ ) { printf("%lld ", ans[i]); } cout << endl; } return 0; } ```
- 难点:
主要二维vector不太会用。
- 难点:
-
-
CF1558A Charmed by the Game
原题链接- 思路
共a+b轮
因为轮流发球,所以A和B分别只可能发球x次和y次
A赢a次, B赢b次。int x = (a + b) / 2; int y = a + b - x;
那么枚举A发球时赢的次数i,那么a的破发次数为a - i
那么此时B的破发次数就是A发球输的次数,那么就是x - i
注意判断,枚举A赢的次数时,它要小于A的发球次数,A的破发次数也要小于等于B的发球次数
还有当发球次数为y时的判断i <= x && a - i <= y
还要注意去重 - 代码
注释详细版#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int main() { int t; cin >> t; while (t -- ) { int a, b; scanf("%d%d", &a, &b); int x = (a + b) / 2, y = a + b - x; map <int, int> f; int cnt = 0, ans[N]; for (int i = 0; i <= a; i ++ )//枚举a发球时赢的次数 { if (i <= x && a - i <= y) { int flag = a - i + x - i;//a接球赢的次数+a发球输的次数 if (f[flag] == 0) { ans[cnt ++ ] = flag; f[flag] ++; } } } swap(x, y); for (int i = 0; i <= a; i ++ )//枚举a发球时赢的次数 { if (i <= x && a - i <= y) { int flag = a - i + x - i;//a接球赢的次数+a发球输的次数 if (f[flag] == 0) { ans[cnt ++ ] = flag; f[flag] ++; } } } printf("%d\n", cnt); sort (ans, ans + cnt); for (int i = 0; i < cnt; i ++ ) printf("%d ", ans[i]); printf("\n"); } return 0; }
#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t -- ) { set<int> v; int a, b; cin >> a >> b; //因为是轮流发球 int x = (a + b) / 2; //A的发球次数 int y = a + b - x;//B的发球次数 // 枚举A发球赢的次数 for (int i = 0; i <= a; i ++ ) { // A的赢的次数-A发球赢的次数==A接球赢的次数 (B发球输的次数) <= B的发球次数 // A发球赢的次数一定大于A发球的次数 if (a - i <= y && x >= i) { // 破发总次数 int flag = a - i + x - i;//a接球赢的次数+a发球输的次数(B接球赢的次数) v.insert(flag); } } swap(a, b); //因为是轮流发球 x = (a + b) / 2; //A的发球次数 y = a + b - x;//B的发球次数 // 枚举A发球赢的次数 for (int i = 0; i <= a; i ++ ) { // A的赢的次数-A发球赢的次数==A接球赢的次数 (B发球输的次数) <= B的发球次数 // A发球赢的次数一定大于A发球的次数 if (a - i <= y && x >= i) { int flag = a - i + x - i;//a接球赢的次数+a发球输的次数(B接球赢的次数) v.insert(flag); } } cout << v.size() << endl; map<int, int> ma; for (auto i:v) { cout << i << " "; } cout << endl; } return 0; }
- 思路
-
CF1579D Productive Meeting
原题链接- 题意
给你 n个数,每次操作从这 n 个数种挑出 2 个大于 0 的数,对这两个数分别 -1。
求最大的可能的操作次数。 - 思路,使用优先队列,但是由于要输出的是下标,那么就用结构体优先队列,每次取出最大的两个数,-1,如果大于0就在扔回堆里,直到堆里的数的个数不足2为止。
- 代码
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; struct node { int a, i; bool operator< (const node & x) const { return a < x.a; } }; priority_queue<node> q; int main() { int t; cin >> t; while (t -- ) { while (!q.empty()) q.pop(); int n; scanf("%d", &n); for (int i = 1; i <= n; i ++ ) { int x; scanf("%d", &x); if(x > 0) q.push({x, i}); } // while (!q.empty()) // { // node tt = q.top(); // cout << tt.i << " "; // q.pop(); // } // cout << endl << endl; int ans1[N]; int ans2[N]; int cnt = 0; while (q.size()>= 2) { node x = q.top(); q.pop(); node y = q.top(); q.pop(); x.a--; y.a--; ans1[cnt] = x.i; ans2[cnt] = y.i; cnt++; // cout << x.i << y.i << endl; if (x.a > 0) q.push(x); if (y.a > 0) q.push(y); } cout << cnt << endl; for (int i = 0; i < cnt; i ++ ) { printf("%d %d\n", ans1[i], ans2[i]); // cout << ans1[i] << " " << ans2 << endl; } } return 0; }
- 题意
-
CF1579C Ticks
原题链接- 题意,看图中所有星号部分,能否全部被划分为长度大于等于k的勾形。
- 思路
存一个字符数组,再存一个数字数组记录状态(0为.,1为*),然后枚举每个*作为勾的交叉点,然后向上枚举,如果它的大小大于等于k,就将数字数字对应位置的1改为0,最后判断有没有全部都被改成0即可。 - 代码
#include<bits/stdc++.h> using namespace std; const int N = 100 + 10; char g[N][N]; int vis[N][N], n, m, k; void check(int x, int y) { int cnt = 0; while (1) { if (g[x - cnt][y - cnt] != '*' || g[x - cnt][y + cnt] != '*' || x < 1 || x > n || y < 1 || y > m) break; cnt ++; } cnt -= 1;//因为初始是0时也判断了一次,所以-1 if (cnt >= k) { vis[x][y] = 0; for (int i = 1; i <= cnt; i ++ ) { vis[x - i][y - i] = 0; vis[x - i][y + i] = 0; } } } int main() { int t; cin >> t; while (t -- ) { cin >> n >> m >> k; memset(vis, 0, sizeof vis); for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= m; j ++ ) { cin >> g[i][j]; if (g[i][j] == '*') vis[i][j] = 1; } } for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= m; j ++ ) { if (g[i][j] == '*') check(i, j); } } bool f = 0; for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= m; j ++ ) { if (vis[i][j] == 1) { cout << "NO" << endl; f = 1; break; } } if (f) break; } if (!f) cout << "YES" << endl; } return 0; }
-
CF1545A AquaMoon and Strange Sort
原题链接- 思路
因为要使它最后还都是向右的话,肯定要交换偶数次,那么只要当前数和它的目标位置的距离是偶数的话,那么它们交换之后还是都朝右的,其他数的交换不会影响到,因为换过来再换过去,别的数都还在原位。
只要两个数所在位置的奇偶性相同,那么它们的距离就是偶数。
那么只要在存数的时候记录一下这个数在奇/偶有几个,然后排序,看它和之前存的相比,有没有在相同位置上的数,有的话说明被用过了就-1,如果没有就说明它不符合要求,直接break输出NO即可。 - 代码
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int num[N]; int f[N][3]; int main() { int t; cin >> t; while (t -- ) { memset(f, 0, sizeof f); int n; cin >> n; for (int i = 1; i <= n; i ++ ) { cin >> num[i]; f[num[i]][i % 2] ++ ; } sort(num + 1, num + 1 + n); bool flag = 0; for (int i = 1; i <= n; i ++ ) { if (f[num[i]][i % 2] == 0) //如果不存在和它在相同位置写上的数 { flag = 1; break; } //用完个数-1 f[num[i]][i % 2] --; } if (flag) cout << "NO" << endl; else cout << "YES" << endl; } return 0; }
- 思路
CF R1300-R1500(做题记录)
于 2021-11-01 13:58:49 首次发布