Codeforces Round #404 (Div. 2) 题解
Posted AC_Arthur
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #404 (Div. 2) 题解相关的知识,希望对你有一定的参考价值。
题目链接:点击打开链接
这次比赛AC了4个水题, 然而我zz了E题写了个bug调了很久没时间写D啦。
A. Anton and Polyhedrons
水题, 加一加就行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 3000+10;
int n;
char s[100];
int main()
scanf("%d", &n);
int ans = 0;
for(int i = 1; i <= n; i++)
scanf("%s", s);
if(s[0] == 'T') ans += 4;
else if(s[0] == 'C') ans += 6;
else if(s[0] == 'O') ans += 8;
else if(s[0] == 'D') ans += 12;
else ans += 20;
printf("%d\\n", ans);
return 0;
B. Anton and Classes
排序就行了, 我们肯定是在一个区间集合中找一个右端点最小的, 在另一个集合里找一个左端点最大的。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 200000+10;
int n, m;
struct node
int l, r;
node(int l=0, int r=0):l(l), r(r)
a[maxn], b[maxn];
bool cmp1(const node& a, const node& b)
if(a.l != b.l) return a.l < b.l;
else return a.r < b.r;
bool cmp2(const node& a, const node& b)
if(a.r != b.r) return a.r < b.r;
else return a.l < b.l;
int main()
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d%d", &a[i].l, &a[i].r);
scanf("%d", &m);
for(int i = 1; i <= m; i++)
scanf("%d%d", &b[i].l, &b[i].r);
int ans = 0;
sort(a+1, a+1+n, cmp2);
sort(b+1, b+1+m, cmp1);
if(a[1].r <= b[m].l)
ans = max(ans, b[m].l - a[1].r);
sort(a+1, a+1+n, cmp1);
sort(b+1, b+1+m, cmp2);
if(b[1].r <= a[n].l)
ans = max(ans, a[n].l - b[1].r);
printf("%d\\n", ans);
return 0;
C. Anton and Fairy Tale
我们可以发现, 当n>m时, 前m天的每天早上一定会被加满谷仓, 在第m+1天开始, 下午的时候, 谷仓里谷子会少m+1个,m+2个...., 所以我们只需要判断某一天cnt, 当cnt(cnt+1)/2 + m >= n, 我们可以发现, 这个是可以二分的, 二分他就行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18 + 10);
const int maxn = 200000+10;
ll n, m;
bool ok(ll mid)
ll cur = mid * (mid + 1) / 2;
return cur + m >= n;
int main()
scanf("%I64d%I64d", &n, &m);
if(n <= m)
printf("%I64d\\n", n);
return 0;
ll l = 1, r = 2e9, ans = INF64;
while(l <= r)
ll mid = (l + r) >> 1;
if(ok(mid))
r = mid - 1;
ans = min(ans, mid);
else l = mid + 1;
printf("%I64d\\n", m + ans);
return 0;
D. Anton and School - 2
D题其实很简单, 最后没时间写了, 我们如果从左向右枚举, 当枚举到一个(的时候, 我们假设一定选这个左括号, 那么我们要在之前的左括号里选0个,1个,2个..., 假设我们枚举到当前左括号, 左边有n个, 右边有m个右括号, 那么我们对答案贡献 sum(C(n,0 ̄n)×C(m,1~n+1)= C(n+m, n+1);
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD = 1e9 + 7;
const int maxn = 2e5 + 10;
LL fac[maxn];
void init()
LL i;
fac[0]=1;
for (LL i = 1; i < maxn; i++)
fac[i] = fac[i - 1] * i % MOD;
LL exgcd(LL a, LL b, LL &x, LL &y)
if (!b) x = 1; y = 0; return a;
LL d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
LL inv(LL a, LL n)
LL x, y;
exgcd(a, n, x, y);
return (x + n) % n;
LL C(LL n, LL m)
return fac[n] * inv(fac[m] * fac[n - m] % MOD, MOD) % MOD;
char s[maxn];
int main()
init();
scanf("%s", s + 1);
int len = strlen(s+1);
int cnt1 = 0, cnt2 = 0;
LL ans = 0;
for(int i = 1; i <= len; i++)
if(s[i] == ')') ++cnt2;
for(int i = 1; i <= len; i++)
// printf("case :%d\\n", i);
if(cnt2 == 0) break;
if(s[i] == '(')
// printf("%d %d=", cnt1, cnt2);
ans = (ans + C(cnt1+cnt2, cnt1+1)) % MOD;
// ans = (ans + cnt2) % MOD;
// printf("%d\\n", C(cnt1+cnt2, min(cnt1, cnt2)));
++cnt1;
else --cnt2;
// printf("%d\\n", ans);
printf("%I64d\\n", ans);
return 0;
E. Anton and Permutation
这种xjb更新,xjb询问的,我们就分块+二分暴力去搞就行啦。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18 + 10);
const int maxn = 200000+10;
int n, q;
int belong[maxn]; /// ÿ���������ĸ���
int block; /// ��Ĵ�С
int num; /// ��ĸ���
int r[maxn], l[maxn]; /// ÿ������ұ߽�
ll sum[maxn]; /// ����ά������Ϣ
ll cnt[maxn];
int a[maxn];
vector<int> res[maxn/10];
void build()
block = sqrt(n);
num = n / block;
if(n % block) num++;
for(int i = 1; i <= num; i++)
l[i] = (i-1)*block + 1;
r[i] = i * block;
sum[i] = 0;
cnt[i] = 0;
r[num] = n;
for(int i = 1; i <= n; i++) belong[i] = (i-1)/block+1;
int ccc = 1;
for(int i = 1; i <= num; i++)
for(int j = l[i]; j <= r[i]; j++)
res[i].push_back(ccc);
a[ccc] = ccc;
++ccc;
int query(int x, int y, int cal)
int ans = 0;
if(belong[x] == belong[y])
for(int i = x; i <= y; i++)
if(a[i] < cal) ++ans;
return ans;
else
for(int i = x; i <= r[belong[x]]; i++)
if(a[i] < cal) ++ans;
for(int i = belong[x]+1; i < belong[y]; i++)
int pos = lower_bound(res[i].begin(), res[i].end(), cal) - res[i].begin();
if(pos == (int)res[i].size()) ans += pos;
else if(res[i][pos] != cal) ans += pos;
for(int i = l[belong[y]]; i <= y; i++)
if(a[i] < cal) ++ans;
return ans;
void update(int l, int r)
int be = belong[l];
int bee = belong[r];
int pos = lower_bound(res[be].begin(), res[be].end(), a[l]) - res[be].begin();
res[be].erase(res[be].begin() + pos);
res[be].push_back(a[r]);
sort(res[be].begin(), res[be].end());
pos = lower_bound(res[bee].begin(), res[bee].end(), a[r]) - res[bee].begin();
res[bee].erase(res[bee].begin() + pos);
res[bee].push_back(a[l]);
sort(res[bee].begin(), res[bee].end());
void print()
for(int i = 1; i <= num; i++)
for(int j = l[i]; j <= r[i]; j++)
printf("%d ", res[i][j-l[i]]);
cout<<endl;
int main()
scanf("%d%d", &n, &q);
build();
ll ans = 0;
while(q--)
int l, r;
scanf("%d%d", &l, &r);
if(l > r) swap(l, r);
if(l == r)
printf("%I64d\\n", ans);
continue;
if(l+1 == r)
if(a[l] < a[r]) ++ans;
else --ans;
else
int cur = query(l+1, r-1, a[l]);
int maxv = (r - l - 1) - cur;
ans -= cur;
ans += maxv;
cur = query(l+1, r-1, a[r]);
maxv = (r - l - 1) - cur;
ans += cur;
ans -= maxv;
if(a[l] < a[r]) ++ans;
else --ans;
update(l, r);
swap(a[l], a[r]);
// print();
printf("%I64d\\n", ans);
return 0;
以上是关于Codeforces Round #404 (Div. 2) 题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #404 (Div. 2)
Codeforces Round #404 (Div. 2) 题解
Codeforces Round #404 (Div. 2) 题解
Codeforces Round #404 (Div. 2) C 二分查找