C
用scanf("%s")就会WA..不知道为什么
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 3e5 + 5; int preE[N]; int preW[N]; string f; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; cin >> f; preE[0] = preW[0] = 0; for (int i = 1; i <= n; i++) { if (f[i - 1] == 'W') { preW[i] = preW[i - 1] + 1; preE[i] = preE[i - 1]; } else { preE[i] = preE[i - 1] + 1; preW[i] = preW[i - 1]; } } ll anser = INT_MAX; ll now; for (int i = 1; i <= n; i++) { now = preW[i - 1] - preW[0]; now += preE[n] - preE[i]; anser = min(anser, now); } cout << anser << endl; return 0; }
D
题意:
给你N个非负数(1e5) 要求你求出有多少个区间内 区间和等于区间亦或和 给的数小于220
解:
因为XOR操作中 0^0=0 1^1=0 0^1=1 如果两个数相加有进位操作的话 肯定会损失值
所以我们把0特殊化 直接暴力 如果有位数重复的就不成立 所以每次查询的区间长度不会超过20
复杂度为1e6左右
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 2e5 + 5; ll num[N]; int last = 0; int Left[N]; ll yihuo; ll pre; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; ll anser = 0; for (int i = 1; i <= n; i++) { cin >> num[i]; Left[i] = last; if (num[i]) { last = i; } } ll now; ll i, j; for (i = 1; i <= n; i++) { yihuo = pre = num[i]; for (j = Left[i]; j >= 1;j = Left[j]) { yihuo = yihuo ^ num[j]; pre += num[j]; if (yihuo != pre) { break; } } anser+=i-j; } cout << anser << endl; return 0; }
改进版:我们发现如果L-R区间是满足的 那么 L - R 内任意一个子区间也是满足的 即 L+1 - R 也行
所以每次取完极大满足条件的区间后 当R右移一格时 满足条件的L一定不会在前一个的左边
#include<bits/stdc++.h> using namespace std; int n; long long s[555555]; long long a[555555]; long long ans; int main(){; scanf("%d",&n); for (int i=1;i<=n;i++){ int x; scanf("%d",&x); s[i]=s[i-1]+x; a[i]=a[i-1]^x; } int l=1; for (int r=1;r<=n;r++){ for (;(s[r]-s[l-1])!=(a[r]^a[l-1]);l++); ans+=r-l+1; } printf("%lld\n",ans); }
E
题意:
给你一个N个数(2000)的数列 每次操作可以让长度为K的连续序列内的最小值去除 你必须要去除Q次
假设这Q次中去除的最大的为X最小的为Y 问你X-Y最小可以是多少
解:
从1到N 枚举Y=A[i]
然后再找出全部原数列中可以删的不小于A[i]的数
如果找出的数的数目小于Q则不满足条件 跳过 反之则排序去第Q个减去A[i]即为一种的答案
总复杂度为N2LOGN
#include<bits/stdc++.h> using namespace std; int a[2005], b[2005], c[2005]; int n, k, q, ans; int main() { scanf("%d%d%d", &n, &k, &q); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); } ans = 1e9 + 1; for (int i = 1; i <= n; i++) //枚举每个作为Y的a[i] { int l = 0; int cnt = 0; for (int j = 1; j <= n + 1; j++) if (a[i] > a[j]) { if (!l) //如果前面没有比a[i]大的 先跳过 { continue; } int r = j - 1; //这样L到R区间内所有数都是不小于a[i]的 for (int p = l; p <= r; p++) { b[p] = a[p]; } sort(b + l, b + r + 1); for (int p = l; p + k - 1 <= r; p++) //L到R区间内得有不小于K数目的数 { c[++cnt] = b[p]; //把能删的最小的都删掉 } l = 0; } else if (!l) //枚举到不小于a[i]的 { l = j; } if (cnt < q) { continue; } sort(c + 1, c + cnt + 1); //printf("%d\n",c[q]); ans = min(ans, c[q] - a[i]); } printf("%d\n", ans); }