每次动态更新上下界,最后二分判断一下界内的被删除数字即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 #include <bits/stdc++.h> using namespace std;const int N = 2e5 + 10 ;const int inf = 1 << 30 ;const long long llinf = 1ll << 60 ;const double PI = acos (-1 );#define lowbit(x) (x&-x) typedef long long ll;typedef double db;typedef pair<int , int > pii;typedef pair<ll, ll> pll;typedef pair<db, db> pdd;typedef pair<ll, int > pli;int n, m, k, q;void work () { cin >> n; ll l = 0 , r = 1e10 , x; vector<int > vec; for (int i = 1 , op; i <= n; i++) { cin >> op >> x; switch (op) { case 1 : { l = max (x, l); break ; } case 2 : { r = min (x, r); break ; } case 3 : { vec.push_back (x); break ; } } } if (l > r) { cout << 0 << endl; return ; } sort (vec.begin (), vec.end ()); unique (vec.begin (), vec.end ()); auto it1 = lower_bound (vec.begin (), vec.end (), l); auto it2 = --upper_bound (vec.begin (), vec.end (), r); if (it2 - it1 < 0 || (*it1) < l || (*it2) > r) { cout << r - l + 1 << endl; } else { cout << r - l + 1ll - (ll)(it2 - it1 + 1 ) << endl; } } int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cout.tie (0 ); int t; cin >> t; while (t --> 0 ) { work (); } }
对后手而言,显然把最大的\(x\) 个数取反了是最优的。所以作为先手,我们枚举去掉最大的\(1\dots
k\) 个数,最终结果是多少,排序+前缀和即可,注意判断边界。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <bits/stdc++.h> using namespace std;const int N = 2e5 + 10 ;const int inf = 1 << 30 ;const long long llinf = 1ll << 60 ;const double PI = acos (-1 );#define lowbit(x) (x&-x) typedef long long ll;typedef double db;typedef pair<int , int > pii;typedef pair<ll, ll> pll;typedef pair<db, db> pdd;typedef pair<ll, int > pli;ll a[N]; void work () { int n, k, x; cin >> n >> k >> x; for (int i = 1 ; i <= n; i++) { cin >> a[i]; } sort (a + 1 , a + n + 1 ); ll val = -1e10 ; for (int i = 2 ; i <= n; i++) a[i] += a[i - 1 ]; if (n == k) val = 0 ; for (int i = 0 ; i <= k; i++) { if (n - i < 0 ) break ; val = max (val, 2ll * a[max (0 , n - i - x)] - a[n - i]); } cout << val << endl; } int main () { ios::sync_with_stdio (0 ); cin.tie (0 ); cout.tie (0 ); int t; cin >> t; while (t --> 0 ) { work (); } }
题意可知,对于每个整除n的\(k\) ,每一个下标组 \[
\begin{gather}
\{1,1+k,1+2k\dots 1+(\frac n k -1)k\}, \\\\
\{2,2+k,2+2k\dots 2+(\frac n k -1)k\}, \\\\
\dots \\\\
\{k,2k\dots n\}
\end{gather}
\] 组内的元素对某个数\(m\) 同余。
观察题目可以发现,我们实际上并不关心\(m\) 是多少,只需知道存不存在这样的\(m\) 。
对于这样一个式子: \[
\begin{align}
a \equiv b\pmod M \\\\
b \equiv c\pmod M \\\\
\end{align}
\] 移项得: \[
\begin{align}
a-b \equiv 0\pmod M \\\\
b-c \equiv 0\pmod M \\\\
\end{align}
\] 等效于: \[
gcd(a -b,b-c) \not= 1
\]