Problems: http://codeforces.com/contest/1420
A. Cubes Sorting
When the array is strictly descending we need (frac{n(n-1)}{2}) operations.
The number of operations we need is also the number of inversions in the array.
交错代码 × 1
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
int t, n;
cin>>t;
while(t--)
{
cin>>n;
int cnt=0;
for (register int lst=2147483647, a, i = 1; i <= n; ++i)
{
cin>>a;
if (a<lst) ++cnt;
lst=a;
}
if (cnt==n) printf("NO
");
else printf("YES
");
}
return 0;
}
B. Rock and Lever
(a_i;&;a_jge a_iotimes a_j) means the highest bits in (a_i) and (a_j) are the same
.
用 bool 存 int × 1
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 100005;
bool Bit[MAXN][40];
int BitTOT[MAXN];
long long Cnt[40];
long long Calc(long long x)
{
return (1ll*x*(x-1))>>1;
}
int main()
{
ios::sync_with_stdio(false);
int t, n, ones=0, zeroes=0;
cin >> t;
while (t--)
{
for (int i = 0; i < 40; ++i) Cnt[i]=0;
cin >> n;
ones=0, zeroes=0;
for (register int a, i = 1; i <= n; ++i)
{
cin >> a;
BitTOT[i]=0;
while (a)
{
Bit[i][++BitTOT[i]] = a&1;
a>>=1;
}
++Cnt[BitTOT[i]];
}
long long Ans = 0;
for (int i = 0; i < 40; ++i) Ans += Calc(Cnt[i]);
cout<<Ans<<endl;
}
return 0;
}
C1. Pokémon Army (easy version)
DP, choose (a_i) or not
看错题意 × 1
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 3e5 + 10;
int t, n, q;
int a[MAXN];
long long Dp[2];
int main()
{
cin >> t;
while (t--)
{
cin >> n >> q;
Dp[0]=0, Dp[1]=0; long long Tmp0=0, Tmp1=0;
for (register int i = 1; i <= n; ++i)
{
cin >> a[i];
Tmp0 = max(Dp[0], Dp[1]-a[i]);
Tmp1 = max(Dp[1], Dp[0]+a[i]);
Dp[1] = Tmp1, Dp[0] = Tmp0;
}
cout << max(Dp[1], Dp[0]) << endl;
}
return 0;
}
C2. Pokémon Army (hard version)
一种方法是用线段树维护。复杂度带个 (log) 。
当然也有 (O(n)) 做法:
从例子入手。
比如说:1 3 5 7 9 5 2 4 6 8 10
显然会选择 +9 -2 +10
也就是选择了最长单调不递减序列的末尾和最长单调递减序列的末尾
差分
那么对于上面的例子,差分后答案是 1 + (9 - 1) + (10 - 2)
把差分数组里面所有正数加起来,再加上 (a_1) 即可。
交换只需稍作讨论。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
#define DifUpdate(pos) (dif[pos] = a[pos] - a[pos-1])
#define Recall(pos) if(dif[pos] > 0) Ans -= dif[pos]
#define Calc(pos) if (dif[pos] > 0) Ans += dif[pos]
const int MAXN = 3e5 + 10;
int t, n, q;
int a[MAXN];
int dif[MAXN];
long long Ans = 0;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> t;
while (t--)
{
cin >> n >> q;
Ans = 0;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
DifUpdate(i);
Calc(i);
}
cout << Ans << endl;
dif[0] = 0, dif[n+1] = 0;
a[0] = 0, a[n+1] = 0;
for (int qL, qR, i = 1; i <= q; ++i)
{
cin >> qL >> qR;
swap(a[qL], a[qR]);
if (qL == qR - 1)
{
Recall(qL);
Recall(qR);
Recall(qR+1);
DifUpdate(qL);
DifUpdate(qR);
DifUpdate(qR+1);
Calc(qL);
Calc(qR);
Calc(qR+1);
}
else
{
Recall(qL);
Recall(qR);
Recall(qL+1);
Recall(qR+1);
DifUpdate(qL);
DifUpdate(qR);
DifUpdate(qL + 1);
DifUpdate(qR + 1);
Calc(qL);
Calc(qR);
Calc(qL+1);
Calc(qR+1);
}
cout << Ans << endl;
}
}
return 0;
}
D. Rescue Nibel!
模拟题
加强版:[G. Rikka with Intersections of Paths]
场上:逆元用了ExGCD还写挂了 × 1
没想到阶乘的逆元可以递推(不会逆元) × 1
条件写挂了 × 1
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 3e5+10;
int n, k, l[MAXN], r[MAXN], a[MAXN<<1];
int Mrk[MAXN<<1], MrkSub[MAXN<<1];
long long Ans = 0;
long long Fact[MAXN];
long long InvFact[MAXN];
const long long MOD = 998244353;
long long qpow(long long a, long long b)
{
long long Ans = 1;
while (b)
{
if (b & 1)
{
Ans = Ans * a % MOD;
}
a = a * a % MOD;
b >>= 1;
}
return Ans;
}
long long inv(long long a)
{
return qpow(a, MOD - 2);
}
void GetFact(int n)
{
Fact[0]=1;
for (int i = 1; i <= n; ++i)
{
Fact[i] = Fact[i-1] * i % MOD;
}
}
long long Calc(int n, int m)
{
if (n < m) return 0;
return Fact[n] * (InvFact[m] * InvFact[n-m] % MOD) % MOD;
}
void GetInvFact(int n)
{
// for (int i = 0; i <= n; ++i) InvFact[i] = inv(Fact[i]);
InvFact[n] = inv(Fact[n]);
for (int i = n-1; i >= 0; --i) InvFact[i] = InvFact[i+1] * (i+1) % MOD;
}
int main()
{
// freopen("data.in","r",stdin);
cin >> n >> k;
GetFact(n);
GetInvFact(n);
for (int i = 1; i <= n; ++i)
{
cin >> l[i] >> r[i]; ++r[i];
a[++a[0]]=l[i], a[++a[0]]=r[i];
}
sort(a + 1, a + 1 + a[0]);
a[0] = unique(a + 1, a + a[0] + 1) - a - 1;
for (int i = 1; i <= n; ++i)
{
l[i]=lower_bound(a + 1, a + 1 + a[0], l[i]) - a;
r[i]=lower_bound(a + 1, a + 1 + a[0], r[i]) - a;
++Mrk[l[i]], ++MrkSub[r[i]];
}
for (int tot = 0, i = 1; i <= a[0]; ++i)
{
tot -= MrkSub[i];
NOT!!! if (tot + Mrk[i] >= k)
// {
Ans = (Ans + MOD - Calc(tot, k)) % MOD;
// }
tot += Mrk[i];
// if (tot >= k)
// {
Ans = (Ans + Calc(tot, k)) % MOD;
// }
}
cout << Ans;
return 0;
}