D. Denouncing Mafia

给定一颗树,然后给定\(k\)个起点,对于每个起点来说,从该点到根节点的一条链都会被染色,求最多有几个点会被染色

\(3 \leq n \leq 1e5, 1 \leq k \leq n\)

题解

  • 我们贪心的来看,起点一定会选择在叶子节点,假设叶子节点的数量为\(cnt\),所以如果\(k \geq cnt\),那么答案一定为\(n\)
  • 否则我们可以长链剖分,将每条链剖出来后排序取前\(k\)条链即可
const int N = 1e5 + 10, M = 4e5 + 10;

int n, k;
vector<int> g[N];
int hson[N], dep[N], mx_dep[N], fa[N], sz[N];
int l[N], r[N], id[N], idx, top[N];
int tot, w[N]; void dfs1(int u, int par)
{
sz[u] = 1;
hson[u] = -1;
fa[u] = par;
mx_dep[u] = dep[u] = dep[par] + 1;
for (auto v : g[u])
{
if (v == par)
continue;
dfs1(v, u);
sz[u] += sz[v];
mx_dep[u] = max(mx_dep[u], mx_dep[v]);
if (hson[u] == -1 || mx_dep[v] > mx_dep[hson[u]])
hson[u] = v;
}
} void dfs2(int u, int head)
{
top[u] = head;
l[u] = ++idx;
id[idx] = u;
if (hson[u] != -1)
dfs2(hson[u], head);
for (auto v : g[u])
{
if (v != fa[u] && v != hson[u])
dfs2(v, v);
}
r[u] = idx;
} void solve()
{
cin >> n >> k;
for (int i = 2; i <= n; ++i)
{
int u;
cin >> u;
g[u].push_back(i);
g[i].push_back(u);
}
dfs1(1, 0);
dfs2(1, 1);
int cnt_son = 0;
for (int i = 1; i <= n; ++i)
{
if (sz[i] == 1)
{
cnt_son++;
w[++tot] = dep[i] - dep[top[i]] + 1;
}
}
if (k >= cnt_son)
{
cout << n << endl;
return;
}
sort(w + 1, w + tot + 1, greater<int>());
int ans = 0;
for (int i = 1; i <= k; ++i)
ans += w[i];
cout << ans << endl;
}

L. Less Coin Tosses

给定\(n, 2 \leq n \leq 1e18\),将\(2^n\)个二进制字符串分别分配给两个人,使得两个人获胜的概率相同的情况下未被分配的字符串数量最少

题解

  • 显然只要某一次分配的字符串中\(1\)的个数相同,那么两个人获胜的胜率能够始终相同

  • 所以答案为\(\sum (C_n^i \& 1==1)\)

  • 显然对于组合数的奇偶性,我们知道结论:若\((n \& k==k)\),则\(C_n^k\)为奇数,否则为偶数

  • 也就是说如果\(k\)的二进制是\(n\)的二进制的子集,那么答案贡献\(+1\)

  • 那么显然答案为\(n\)的二进制中\(1\)个数为\(x\),答案为\(2^x\)

const int N = 2e5 + 10, M = 4e5 + 10;

int n;

void solve()
{
cin >> n;
int x = __builtin_popcountll(n);
cout << (1ll << x) << endl;
}

M. Maratona Brasileira de Popcorn

题解

  • 考虑二分答案
  • \(check\)时检查需要几个人才能将所有的玉米吃完,然后与原有人数比较即可
const int N = 2e6 + 10;
int n,m,cnt;
int a[N]; bool check(int mid)
{
int w=1;
int x=mid*cnt;
for(int i=1;i<=n;)
{
if(a[i]-x<=0)
{
x-=a[i];
i++;
}
else
{
x=mid*cnt;
w++;
if(w>m) return false;
}
}
if(w>m ) return false;
else return true;
} void solve()
{
cin>>n>>m>>cnt;
for(int i=1;i<=n;i++) cin>>a[i];
int l=0,r=2e15;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
cout<<l<<endl;
}

J. Jar of Water Game

题解

  • 模拟即可
  • 注意细节:
  1. 拿到鬼牌后不能立刻传递
  2. 一开始的时候有可能已经存在获胜的玩家
  3. 每次判断胜利条件在传递牌之后,判断所有队伍是否胜利
const int N = 1e2 + 10, M = 4e5 + 10;

int n, k;
map<char, int> mp[N];
string cmp = "A23456789DQJK"; void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; ++i)
{
string s;
cin >> s;
for (auto ch : s)
mp[i][ch]++;
if (i == k)
mp[i]['W']++;
}
int now = k;
bool flag = true;
int cur = 4;
while (true)
{
int nxt = now + 1;
if (nxt > n)
nxt = 1;
if (mp[now]['W'] > 0 && flag == false)
mp[nxt]['W']++, mp[now]['W']--, flag = true;
else
{
if (mp[now]['W'] > 0 && flag == true)
flag = false;
int mi = INF;
char ch;
for (auto [x, y] : mp[now])
{
if (y == 0)
continue;
if (x == 'W')
continue;
if (y < mi)
{
mi = y;
ch = x;
}
else if (y == mi)
{
if (cmp.find(x) < cmp.find(ch))
ch = x;
}
}
mp[now][ch]--;
mp[nxt][ch]++;
}
int ans = -1;
char ans_ch;
for (int i = 1; i <= n; ++i)
{
int cnt = 0;
bool ok = false;
char c;
for (auto [x, y] : mp[i])
{
cnt += (y > 0);
if (y == 4)
{
ok = true;
c = x;
}
}
if (ok && cnt == 1)
{
if (ans == -1)
{
ans = i;
ans_ch = c;
}
else if (cmp.find(c) < cmp.find(ans_ch))
{
ans = i;
ans_ch = c;
}
}
}
if (ans != -1)
{
cout << ans << endl;
return;
}
now = nxt;
}
}

A. Artwork

题解

  • \(O(n^2)\)将所有相交的监控用并查集合并,然后并查集中维护四种信息:是否与左墙接触\(left\),\(right\),\(up\),\(down\)
  • 然后判断是否有监控集合同时接触左墙和右墙,上墙和下墙,左墙和上墙,右墙和下墙之一即可
const int N = 1e4 + 10;
const int K = 1010;
int n, m, k, x[K], y[K], R[K];
bool f[K][5]; //up 1 down 2 left 3 right 4
const int UP = 1;
const int DOW = 2;
const int LE = 3;
const int RI = 4; bool check(int i){
return ((f[i][UP] && f[i][LE]) || (f[i][UP] && f[i][DOW]) || (f[i][LE] && f[i][RI]) || (f[i][RI] && f[i][DOW]));
} bool xiangjiao(int e1, int e2){
int dis=(x[e1]-x[e2])*(x[e1]-x[e2])+(y[e1]-y[e2])*(y[e1]-y[e2]);
int rr=(R[e1]+R[e2])*(R[e1]+R[e2]);
return dis<=rr;
} int fa[K]; int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
} void merg(int a, int b){
a = find(a);
b = find(b);
if(a == b) return;
f[b][UP] |= f[a][UP];
f[b][DOW] |= f[a][DOW];
f[b][LE] |= f[a][LE];
f[b][RI] |= f[a][RI];
fa[a] = b;
} void solve()
{
for(int i = 1;i < K;i++) fa[i] = i;
bool ans = false;
cin >> m >> n >> k;
for(int i = 1;i <= k;i++){
cin >> x[i] >> y[i] >> R[i];
if(x[i] - R[i] <= 0) f[i][UP] = true;
if(x[i] + R[i] >= m) f[i][DOW] = true;
if(y[i] - R[i] <= 0) f[i][LE] = true;
if(y[i] + R[i] >= n) f[i][RI] = true; if(check(i)) ans = true;
} if(ans){
cout << "N";
return;
} for(int i = 1;i <= k;i++){
for(int j = i + 1;j <= k;j++){
if(xiangjiao(i, j)){
merg(i, j);
if(check(find(j))){
cout << "N";
return;
}
}
}
} cout << "S";
}

F. Forests in Danger

给定\(n\)条平行于\(x\)轴或\(y\)轴的线段,每条线段能够覆盖的范围是一个矩阵,线段上每个点到矩阵边的最小距离都为\(r\),给定一块矩阵区域\(p\),请你确定一个最小的\(r\),能够使得\(n\)条线段产生的矩阵与矩阵\(p\)的重合部分的面积至少是矩阵\(p\)面积的\(\%P\)

题解:二分答案 + 矩形面积并

  • 显然二分答案
  • \(check\)时我们可以求出每个矩阵与矩阵\(p\)的交,交集同样也是一个矩阵
  • 然后对每一个交的矩阵求矩形面积并即可,最后和矩阵\(p\)的面积比较一下即可
  • \(tips\):利用线段树计算矩形的长时,需要对长度\(-1\),因为\([2,5]\)的长度在计算矩形面积时应该为\(3\),但是线段树中会返回\(4\)
const int N = 2e5 + 10, M = 4e5 + 10;

int n, P, x3, x4, y3, y4, m = 2e5 + 5;
struct Line
{
int x1, y1, x2, y2;
} line[N];
struct Mat : Line
{
} mat[N]; struct info
{
int mi, cnt;
friend info operator+(const info &a, const info &b)
{
info c;
if (a.mi == b.mi)
{
c.mi = a.mi;
c.cnt = a.cnt + b.cnt;
}
else if (a.mi < b.mi)
{
c.mi = a.mi;
c.cnt = a.cnt;
}
else
{
c.mi = b.mi;
c.cnt = b.cnt;
}
return c;
}
info(int mi = 0, int cnt = 0) : mi(mi), cnt(cnt) {}
};
struct SEG
{
int lazy;
info val;
} seg[N << 2]; void up(int id)
{
seg[id].val = seg[lson].val + seg[rson].val;
} void settag(int id, int tag)
{
seg[id].val.mi += tag;
seg[id].lazy += tag;
} void down(int id)
{
if (seg[id].lazy == 0)
return;
settag(lson, seg[id].lazy);
settag(rson, seg[id].lazy);
seg[id].lazy = 0;
} void build(int id, int l, int r)
{
seg[id].lazy = 0;
if (l == r)
{
seg[id].val = info(0, 1);
return;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
up(id);
} void modify(int id, int l, int r, int ql, int qr, int val)
{
if (ql <= l && r <= qr)
{
settag(id, val);
return;
}
down(id);
int mid = l + r >> 1;
if (qr <= mid)
modify(lson, l, mid, ql, qr, val);
else if (ql > mid)
modify(rson, mid + 1, r, ql, qr, val);
else
{
modify(lson, l, mid, ql, qr, val);
modify(rson, mid + 1, r, ql, qr, val);
}
up(id);
} bool check(int r)
{
build(1, 1, m);
vector<array<int, 4>> evt;
vector<int> vec;
for (int i = 1; i <= n; ++i)
{
auto [x1, y1, x2, y2] = line[i];
mat[i] = {x1 - r, y1 - r, x2 + r, y2 + r};
}
for (int i = 1; i <= n; ++i)
{
auto [x1, y1, x2, y2] = mat[i];
int lx = max(x1, x3), ly = max(y1, y3);
int rx = min(x2, x4), ry = min(y2, y4);
if (lx < rx && ly < ry)
{
// 别忘记右端点 -1
evt.push_back({ly, -1, lx, rx - 1}); // 入边
evt.push_back({ry, 1, lx, rx - 1}); // 出边
}
}
sort(all(evt));
int ans = 0;
int sum = seg[1].val.cnt;
int preY = 0;
for (auto [y, op, l, r] : evt)
{
int len = sum;
if (seg[1].val.mi == 0)
len -= seg[1].val.cnt;
ans += (y - preY) * len;
if (op == -1)
modify(1, 1, m, l, r, 1);
else
modify(1, 1, m, l, r, -1);
preY = y;
}
int area = (x4 - x3) * (y4 - y3);
return ans * 100 >= area * P;
} void solve()
{
cin >> n;
for (int i = 1; i <= n; ++i)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
line[i] = {x1 + 1, y1 + 1, x2 + 1, y2 + 1};
}
cin >> P;
cin >> x3 >> y3 >> x4 >> y4;
x3++, y3++, x4++, y4++;
int l = 0, r = 1e9;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid))
r = mid - 1;
else
l = mid + 1;
}
cout << l << endl;
}

2019-2020 ACM-ICPC Brazil Subregional Programming Contest的更多相关文章

  1. (寒假GYM开黑)2018-2019 ACM-ICPC Brazil Subregional Programming Contest

    layout: post title: 2018-2019 ACM-ICPC Brazil Subregional Programming Contest author: "luowenta ...

  2. 2018-2019 ACM-ICPC Brazil Subregional Programming Contest PART (10/13)

    $$2018-2019 ACM-ICPC Brazil Subregional Programming Contest$$ \(A.Slackline\ Adventure\) \(B.Marbles ...

  3. 2019-2020 ACM-ICPC Brazil Subregional Programming Contest (11/13)

    \(2019-2020\ ACM-ICPC\ Brazil\ Subregional\ Programming\ Contest\) \(A.Artwork\) 并查集,把检测区域能在一起的检测器放在 ...

  4. 2018-2019 ACM-ICPC Brazil Subregional Programming Contest

    A:留坑 B:二维sg函数,特判边界情况 //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize(4) / ...

  5. Gym.101908 Brazil Subregional Programming Contest(寒假自训第六场)

    这几天睡眠时间都不太够,室友晚上太会折腾了,感觉有点累,所以昨天的题解也没写,看晚上能不能补起来. B . Marbles 题意:给定N组数(xi,yi),玩家轮流操作,每次玩家可以选择其中一组对其操 ...

  6. 2013-2014 ACM-ICPC Brazil Subregional Programming Contest 题解

    [题目链接] 这场比赛题面英文都好长... ... A - Zero or One 模拟. #include <bits/stdc++.h> using namespace std; in ...

  7. ACM ICPC, JUST Collegiate Programming Contest (2018) Solution

    A:Zero Array 题意:两种操作, 1 p v  将第p个位置的值改成v  2  查询最少的操作数使得所有数都变为0  操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...

  8. ACM ICPC, Amman Collegiate Programming Contest (2018) Solution

    Solution A:Careful Thief 题意:给出n个区间,每个区间的每个位置的权值都是v,然后找长度为k的区间,使得这个区间的所有位置的权值加起来最大,输出最大权值, 所有区间不重叠 思路 ...

  9. Codeforces Gym101473 A.Zero or One (2013-2014 ACM-ICPC Brazil Subregional Programming Contest)

    代码: #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #i ...

  10. Codeforces Gym101473 F.Triangles-前缀和 (2013-2014 ACM-ICPC Brazil Subregional Programming Contest)

    前缀和. 代码: 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include< ...

随机推荐

  1. 【转】一种Vue应用程序错误/异常处理机制

    在前端应用程序中,最常见的错误/异常类型可能包括以下几种: 语法错误:使用了一些错误的语法 运行时错误:由于执行期间的非法操作导致的 逻辑错误:由于程序逻辑错误 Http 错误:API 返回的错误 有 ...

  2. CSS & JS Effect – Section Design Waves

    介绍 Section Waves 长这样       左边是没有 waves, 右边是加了 waves. 它的作用就是点缀. 让画面有一点 "Design" 的感觉. 参考 You ...

  3. SpringBoot——整合SSM(主要整合MyBatis)

    基于SpringBoot整合SSM SpringBoot整合Spring(不存在) SpringBoot整合SpringMVC(不存在) SpringBoot整合MyBatis(主要) Spring整 ...

  4. namenode rpc 请求队列调优

    当 datanode 上新写完一个块,默认会立即汇报给 namenode.在一个大规模 Hadoop 集群上,每时每刻都在写数据,datanode 上随时都会有写完数据块然后汇报给 namenode ...

  5. Python实现多维傅里叶变换

    技术背景 在前面一篇文章中,我们介绍了一维离散傅里叶变换和快速傅里叶变换的基本原理和简单的代码实现.本文补充一个多维傅里叶变换的场景,以及简单的Python实现. 二维傅里叶变换 首先回顾一下上一篇文 ...

  6. MySQL笔记--数据库定时备份与恢复

    利用crontab定时.利用mysqldump备份 编写sh启动脚本时记得赋予执行权限(x) 如果没有mysqldump命令执行,基于centos7 yum -y install mysql-clie ...

  7. 智能化IT运维平台建设方案,基于智和信通运维体系的高敏捷二次开发

    随着企业信息进程不断加速,运维人员需要面对越来越复杂的业务和越来越多样化的用户需求,不断扩展的应用需要越来越合理的模式.越来越智能的工具来保障运维能灵活便捷.安全稳定地开展.企业网络规模的不断扩大,从 ...

  8. docker安装过程 - 下载mysql

    1. 下载必要的包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2. 指定虚拟机去哪里安装 docker sudo ...

  9. 06 Word2Vec模型(第一个专门做词向量的模型,CBOW和Skip-gram)

    博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...

  10. MP4 转 TXT 项目与 M3U8 下载脚本

    项目背景 在当今信息社会,视频学习已成为一种重要的知识获取方式.然而,许多用户在观看视频的过程中,效率往往低于预期.为了提升学习效率,我们决定开发一个将 MP4 视频转换为 TXT 文稿的项目.此外, ...