Codeforces 701
A. Cards
直接贪心即可,写法各异。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-6
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
int N, a[105];
bool used[105] = {false};
set<int> st[105];
set<int>::iterator it;
int main()
{
scanf("%d", &N);
int sum = 0, ave;
for(int i=1; i<=N; i++)
{
scanf("%d", &a[i]);
sum += a[i];
st[a[i]].insert(i);
}
ave = sum * 2 / N;
for(int i=(N>>1), j; i>0; i--)
{
for(j=1; j<=N; j++) if(!used[j]) break;
used[j] = true;
int res = ave - a[j];
for(it = st[res].begin(); it != st[res].end(); it++)
{
if(!used[*it])
{
used[*it] = true;
printf("%d %d\n", j, *it);
st[res].erase(it);
break;
}
}
}
return 0;
}
B. Cells Not Under Attack
记录每一行每一列是否被使用过,然后看是减去(行数+列数-1)(都是剩下行和剩下列),还是减去(行数)或者(列数),或者就是这个十字交点被用过的,于是就不减了。
WA了一次,行列写错了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-6
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
ll N, sum, hang, lie;
int M;
bool du[100005] = {false}, lr[100005] = {false};
int main()
{
scanf("%lld%d", &N, &M);
sum = N * N;
hang = lie = N;
int x, y;
while(M--)
{
scanf("%d%d", &x, &y);
if(!du[x] && !lr[y])
{
sum -= hang + lie - 1;
du[x] = true;
lr[y] = true;
hang--; lie--;
}
else if(!du[x])
{
sum -= lie;
hang--;
du[x] = true;
}
else if(!lr[y])
{
sum -= hang;
lie--;
lr[y] = true;
}
printf("%lld ", sum);
}
puts("");
return 0;
}
/*
4 3
3 2
2 2
3 3
*/
C. They Are Everywhere
尺取法,复杂度O(N)。不断尺取,去寻找最小值即为答案。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-6
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
inline int _id(char x)
{
if(x >= 'a' && x <= 'z') return x - 'a';
else return x - 'A' + 26;
}
const int maxN = 1e5 + 7;
int N, ans, sum = 0, type = 0, pos[55] = {0}, pre[maxN] = {0};
char s[maxN];
bool vis[55] = {false};
set<int> st;
int main()
{
scanf("%d", &N); ans = N;
scanf("%s", s + 1);
for(int i=1, id; i<=N; i++)
{
id = _id(s[i]);
pre[i] = pos[id];
pos[id] = i;
if(!vis[id])
{
vis[id] = true;
sum++;
}
}
for(int i=1; i<=N; i++)
{
if(!pre[i])
{
type++;
st.insert(i);
}
else
{
st.erase(pre[i]);
st.insert(i);
}
if(type == sum)
{
int tmp = (*st.rbegin()) - (*st.begin()) + 1;
ans = min(ans, tmp);
}
}
printf("%d\n", ans);
return 0;
}
D. As Fast As Possible
比较困难的数学题了(我物理果然是雾里(大雾)。
画出对应的t-x图:
我们可以列出一个方程组:
指的是总花费时间。
我们假设每个bus向前的花费时间是x,返回接学生花费时间是y,那么,最优解的情况是每一位学生都能上车一次,因为车的载客量是K,所以我们的tim是N除以K向上取整。
然后连立这两个方程就可以通过x、y之间的固定关系求解了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
double L, v1, v2;
int N, K, tim;
int main()
{
scanf("%d%lf%lf%lf%d", &N, &L, &v1, &v2, &K);
tim = N / K + (bool)(N % K);
double ans;
double A = 1. * tim + 1. * (tim - 1.) * (v2 - v1) / (v2 + v1);
double B = (v2 - v1) / A;
ans = L / (B + v1);
printf("%lf\n", ans);
return 0;
}
E. Connecting Universities
一个树上的思维操作,跟结点的size有关哦(非一般size,是有效size)
就是给出2*K个点(一开始我竟然读成了两千个点),然后我们可以画图来看,能发现其中的某些规律。
假设如图,红色的点是题目中说到 的2*K个点。
那么如果要去找最优解,也就是应该这样配对{5, 6}、{1, 4}也可以是{1, 6}、{5, 4}。那么,我们可以从每条边产生的贡献角度来考虑这个问题,1-2这条边要贡献一次,3-5、2-3的边也是会贡献一次,然后为了达成最优解,2-4这条边必须贡献两次,4-6也是必须贡献一次才可以。所以我们不如去看如何处理每条边的贡献。
那么问题似乎被简化了,我们把每个结点的入度的边等效给结点上面去,(代表了3这号点的代表边是2-3),3的子树当中有一个标记点;2的子树中有3个,但是呢一共就只有4个点,所以其实1-2的边只用了4-3=1次。我们要考虑目前点的size和2*K-size的关系。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define eps 1e-9
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, K, head[maxN], cnt, siz[maxN] = {0};
bool op[maxN] = {false};
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<1];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
ll ans = 0;
void dfs(int u, int fa)
{
siz[u] += op[u];
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
dfs(v, u);
siz[u] += siz[v];
}
ans += min(siz[u], 2 * K - siz[u]);
}
inline void init()
{
cnt = 0;
for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{
scanf("%d%d", &N, &K);
init();
for(int i=(K<<1), x; i>=1; i--)
{
scanf("%d", &x); op[x] = true;
}
for(int i=1, u, v; i<N; i++)
{
scanf("%d%d", &u, &v);
_add(u, v);
}
dfs(1, 0);
printf("%lld\n", ans);
return 0;
}