Codeforces Round #672 (Div. 2)
T1
A题给我们一个数列,每次可以交换相邻元素的位置,问我们能不能在 \(\frac{n(n-1)}{2}-1\) 次操作内将元素调整为不下降序列。
刚一看到这道题的时候表示十分蒙,但是看到了 \(\frac{n(n-1)}{2}\) 这个熟悉的式子,想到一个序列的最多逆序对数量也就是 \(\frac{n(n-1)}{2}\) 且仅当序列为严格递减的时候成立,那么我们只需要检查所给序列是否为严格递减序列即可
T2
B题也是给出一个数列,要求求出满足 $i < j\ $ 且 \(a_i\ \oplus\ a_j < a_i\ \&\ a_j\) 的数对的个数。
我们发现,显然有 \((a_i\ \oplus\ a_j)\ \&\ (a_i\ \&\ a_j) = 0\) 成立,那么也就是说我们比较两个数的二进制最高位即可
我们知道 \(1\ \oplus\ 1\ =\ 0\) , \(0\ \oplus\ 1\ =\ 1\)
也就是仅当 \(a_i\) , \(a_j\) 的二进制最高位相同时存在 \(a_i\ \oplus\ a_j < a_i\ \&\ a_j\),那么我们只需要统计每一位作为一个数的二进制最高位出现的次数即可。
T3——1
C题分为 \(\text{easy version}\) 和 \(\text{hard version}\),我只会 \(\text{easy version}\) \kk
题目提供一个序列,要求你求出一个序列 \(b_1\ ,\ b_2\ ,\ b_3\dots\) 使得 \(a_{b_1}\ -\ a_{b_2}\ +\ a_{b_3}\ \dots\) 的值最大
我们定义 \(f_i\) 为选择奇数个元素并选择 \(a_i\) 所能得到的最大值, \(g_i\) 为选择偶数个元素并选择 \(a_i\) 所能得到的最大值
我们有转移:
\(f_i = \max(a_i,a_i+\max\limits_{j=1}^{j<i}g_j)\)
\(g_i = -a_i+\max\limits_{j=1}^{j<i}f_j\)
我们发现在求取 \(\max\limits_{j=1}^{j<i}g_j\) 和 \(\max\limits_{j=1}^{j<i}f_j\) 复杂度不够优秀,我们换一种定义,将 \(f_i\) 定义为 小于等于 \(i\) 的情况下选取偶数个元素所能求得的最大值。 \(g_i\) 同理。
我们可以得到新的转移式
\(f_i = \max(a_i,f_{i-1},a_i+g_{i-1})\)
\(g_i = \max(g_{i-1},-a_i+f_{i-1})\)
我们再使用类似于滚动数组的方式进行空间的优化,可以得到最终的转移式:
\(f = \max(a_i,f,a_i+g)\)
\(g = \max(g,f-a_i)\)
T4
我居然做出来了一道D!!
题意:给出n个区间,以及一个数字 \(m\)
求无序 \(m\) 元组的个数,要求其中的区间有公共点。
解法:优先队列+排列组合,懒得写题解了……嘤嘤嘤
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define ll long long
using namespace std;
int read()
{
int a = 0,x = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){
if(ch == '-') x = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
a = a*10 + ch-'0';
ch = getchar();
}
return a*x;
}
const int P=998244353,N = 1e6+7;
struct node {
int l,r;
friend bool operator < (node a,node b) {return a.r > b.r;}
}arr[N];
bool cmp(node a,node b)
{
return a.l < b.l;
}
int n,m;
priority_queue<node>q;
ll fpow(ll a,ll x)
{
if(x == 0) return 1;
if(x == 1) return a;
ll tmp = fpow(a,x/2);
if(x&1) return tmp*tmp%P*a%P;
else return tmp*tmp%P;
}
ll f[N];
ll C(ll a,ll b)
{
return f[a]*fpow(f[b],P-2)%P*fpow(f[a-b],P-2)%P;
}
int main()
{
n = read(),m = read();
f[0] = 1;
for(int i = 1;i <= n;i ++) f[i] = f[i-1]*i%P;
for(int i = 1;i <= n;i ++) {
arr[i].l = read(),arr[i].r = read();
}
ll ans = 0;
sort(arr+1,arr+1+n,cmp);
for(int i = 1;i <= n;i ++) {
while(!q.empty() && q.top().r < arr[i].l) q.pop();
int tmp = q.size();
// printf("%d \n",tmp);
if(tmp+1>=m) {
(ans += C(tmp,m-1)) %= P;
}
q.push(arr[i]);
}
printf("%lld\n",ans);
}