C - Attention

枚举,计算前缀和即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define MAXN 300005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0){putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
} int N,sum[2][MAXN];
char s[MAXN];
void Solve() {
read(N);
scanf("%s",s + 1);
for(int i = 1 ; i <= N ; ++i) {
sum[0][i] = sum[0][i - 1];sum[1][i] = sum[1][i - 1];
if(s[i] == 'E') sum[0][i]++;
else sum[1][i]++;
}
int ans = N;
for(int i = 1 ; i <= N ; ++i) {
ans = min(i - 1 - sum[0][i - 1] + (N - i - (sum[1][N] - sum[1][i])),ans);
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}

D - Xor Sum 2

等价与一个区间每一数位只能有一个1

我们记录\(nxt[i][j]\)表示第\(i\)位数下一个第\(j\)位是1的位置是什么

我们枚举左端点,然后去计算右端点,取最小的右端点

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0){putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
} int N,a[MAXN],nxt[MAXN][25];
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) read(a[i]);
for(int i = 0 ; i < 20 ; ++i) nxt[N + 1][i] = N + 1; for(int i = N ; i >= 1 ; --i) {
for(int j = 0 ; j < 20 ; ++j) {
if(a[i] >> j & 1) {
nxt[i][j] = i;
}
else nxt[i][j] = nxt[i + 1][j];
}
}
int64 ans = 0;
for(int i = 1 ; i <= N ; ++i) {
int r = N;
for(int j = 0 ; j < 20 ; ++j) {
int t = nxt[i][j];
if(t != N + 1) r = min(r,nxt[t + 1][j] - 1);
}
ans += (r - i + 1);
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}

E - Range Minimum Queries

二分一个差值,枚举最小值,我们会得到一个可取区间

对于枚举的最小值,我们把区间里所有大于等于它的都标成1,对于一段连续的1区间,统计一下区间里有多少个数在范围内,记为\(cnt\),设长度为L,这个区间可以满足的询问个数就是\(min(L - K + 1,cnt)\)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 2005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,K,Q;
int a[MAXN],val[MAXN],tot; bool check(int mid) {
for(int i = 1 ; i <= tot ; ++i) {
int l = val[i],r = val[i] + mid;
int res = 0,st = 0,ed = -1,cnt = 0;
for(int j = 1 ; j <= N ; ++j) {
if(a[j] >= l) {
if(!st) st = ed = j;
ed = max(ed,j);
if(a[j] <= r) ++cnt;
}
else {
if(ed - st + 1 >= K) {
res += min(cnt,(ed - st + 1) - K + 1);
}
st = 0,ed = -1;cnt = 0;
}
}
if(ed - st + 1 >= K) {
res += min(cnt,(ed - st + 1) - K + 1);
}
if(res >= Q) return true;
}
return false;
}
void Init() {
read(N);read(K);read(Q);
for(int i = 1 ; i <= N ; ++i) {
read(a[i]);
val[i] = a[i];
}
sort(val + 1,val + N + 1);
tot = unique(val + 1,val + N + 1) - val - 1; }
void Solve() {
int L = 0,R = val[tot] - val[1];
while(L < R) {
int mid = (L + R) >> 1;
if(check(mid)) R = mid;
else L = mid + 1;
}
out(L);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

F - Donation

感觉这道题和之前见过的某道题有点一样,又不太一样……

智商--,看了好久题解才想明白一点。。。

就是……我们先想一下,我们如果按照每个点交钱的顺序写下一个序列

对于第k次选走的点,我们需要的是我们钱数\(w\),需要有\(w >= \sum_{i = 1}^{k}B_{id[i]} + max(A_{id[k]} - B_{id[k]},0)\)

最后我们需要的是序列最大值,我们要最大值最小

并且,要求这个序列付完钱的点,之后不会再经过了

我们对于每个点求一个\(C[i]\)为\(max(A[i] - B[i],0)\)

我们发现,如果一个在\(C[i]\)最大值被选择之前,答案的下限在不断提高

那么我们可能会考虑到,我们要拿走u点之后,我们的图可能会裂成很多子图,我们需要进入其中一个子图,然后将剩下子图的B连带u点累加起来加上\(C[u]\)来累加答案

那么,在最大值拿走之前,假设最大值拿走之后我们进入的子图是\(G_{i}\),那么,\(G_{i}\)里的任何一点\(w\)为什么不能先于u之前拿走呢?

这是我很难想明白的一件事,我现在也许能谈一下理解

当\(w\)点在\(u\)之前时,\(B[w]\)必定会被统计到答案的一个下限中,如果\(w\)在\(u\)点之后,\(B[w]\)可能不会累加进最后的答案用来更新,也可能会,而我们希望的是答案更优秀,\(w\)在\(u\)之前答案不可能变小,而\(w\)在\(u\)之后,答案可能会变小但是绝对不会变大,所以我们把其他子图访问完之后选择访问这个子图

我们发现,这刚刚好是一个子问题,我们对这个子图取出最大值作为根,然后重新求一下这个子图的答案就可以,我们可以用dp解决这个问题,对于每个子图都进入一遍求值

然而,好像又有了一个新的问题,我们怎么求每次去掉最大值后,每个子图里的最大值,暴力求显然是\(n^2\)的

我们发现,全局最大值和每个子图里的最大值连边,每个子图里的最大值和去掉最大值后新裂成的子图最大值连边,刚好可以在图中构建出一棵树

而C值最小的点,必然是叶子

我们按C从小到大遍历每个点,访问周边的所有点,如果周边的点有C值小于它的,就让周边的点所在的子图的最大值(用并查集维护)作为它的儿子就好了

写出来的代码非常清晰,又简单好写,思维含量又高,可以说是虐我这种蒟蒻的好题了。

代码

#include <bits/stdc++.h>
//#define ivorysi
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eps 1e-8
#define mo 974711
#define MAXN 200005
#define pii pair<int,int>
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,M;
struct node {
int to,next;
}E[MAXN * 2];
int head[MAXN],sumE,id[MAXN],ra[MAXN],f[MAXN];
int64 A[MAXN],B[MAXN],C[MAXN],dp[MAXN],siz[MAXN];
vector<int> son[MAXN];
int getfa(int x) {
return f[x] == x ? x : f[x] = getfa(f[x]);
}
bool cmp(int s,int t) {
return C[s] < C[t];
}
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void Init() {
read(N);read(M);
for(int i = 1 ; i <= N ; ++i) {
read(A[i]);read(B[i]);C[i] = max(A[i] - B[i],0LL);
id[i] = i;
}
sort(id + 1,id + N + 1,cmp);
for(int i = 1 ; i <= N ; ++i) ra[id[i]] = i;
int u,v;
for(int i = 1 ; i <= M ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
}
}
void dfs1(int u) {
siz[u] += B[u];
for(auto v : son[u]) {
dfs1(v);
siz[u] += siz[v];
}
}
void dfs2(int u) {
if(son[u].size() == 0) {
dp[u] = B[u] + C[u];
return;
}
dp[u] = 1e18;
for(auto v : son[u]) {
dfs2(v);
dp[u] = min(siz[u] - siz[v] + max(C[u],dp[v]),dp[u]);
}
}
void Solve() {
for(int i = 1 ; i <= N ; ++i) f[i] = i;
for(int i = 1 ; i <= N ; ++i) {
int u = id[i];
for(int j = head[u] ; j ; j = E[j].next) {
int v = E[j].to;
if(ra[getfa(v)] < ra[u] && getfa(v) != u) {
son[u].pb(getfa(v));
f[getfa(v)] = u;
}
}
}
dfs1(id[N]);
dfs2(id[N]);
out(dp[id[N]]);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}

【AtCoder】ARC098题解的更多相关文章

  1. AtCoder ExaWizards2019题解

    AtCoder ExaWizards2019题解 AtCoder (因为代码直接用模板写的,可能有点冗长) A.Regular Triangle 给你三根棍子的长度,问你能否用他们组成等边三角形. 什 ...

  2. 【赛时总结】 ◇赛时·I◇ AtCoder ARC-098

    ◆赛时I◆ ARC-098 ■试题&解析■ ◆本场最水◆ C-Attention 长点儿信心吧-- [AtCoder ARC-098 C] [解析] 既然只存在左右(东西)两个朝向,那么领导右 ...

  3. KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解

    KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...

  4. AT2370 Piling Up

    https://www.luogu.org/jump/atcoder/2370 题解 答案不是\(2^{2m}\)因为每轮的第一次取球可能会不够. 我们可以设\(dp[i][j]\)表示到了第\(i\ ...

  5. Triple Shift

    来源:Atcoder ARC 136 B - Triple Shift (atcoder.jp) 题解:这道题我们不可能去硬模拟(大多数这种题都不能这样去模拟的),然后我们就要去发现特性, 发现把 a ...

  6. 重修 Slope Trick(看这篇绝对够!)

    Slope Trick 算法存在十余载了,但是我没有找到多少拍手叫好的讲解 blog,所以凭借本人粗拙的理解来写这篇文章. 本文除标明外所有图片均为本人手绘(若丑见谅),画图真的不容易啊 qwq(无耻 ...

  7. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  8. AtCoder ExaWizards 2019 简要题解

    AtCoder ExaWizards 2019 简要题解 Tags:题解 link:https://atcoder.jp/contests/exawizards2019 很水的一场ARC啊,随随便便就 ...

  9. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

随机推荐

  1. winform程序关闭界面时弹出提示框

    void Form1_FormClosing(object sender, FormClosingEventArgs e){ if (MessageBox.Show( "窗口关闭后,数据即将 ...

  2. Oracle和SQL SERVER在SQL语句上的差别

    Oracle与Sql server都遵循SQL-92标准:http://owen.sj.ca.us/rkowen/howto/sql92F.html,但是也有一些不同之处,差别如下: Oracle中表 ...

  3. POJ 2387 Til the Cows Come Home (图论,最短路径)

    POJ 2387 Til the Cows Come Home (图论,最短路径) Description Bessie is out in the field and wants to get ba ...

  4. 【codevs4696】等差数列

    题目大意:给定 N 个整数组成的集合,向集合中添加一个整数,使得这 N+1 个整数组成等差数列,求这样的整数有多少个. 题解: 引理1:若原集合中只有一个元素,则有无数种可能. 引理2:若原集合中有且 ...

  5. Python基础学习(二)

    前一段时间学习了Python数据类型,语句和函数,目前书写python的新特性,继续练手!!!! 一.切片 之前我们从python的list 或者 tuple中取得元素都是这样写,显然不够灵活 lis ...

  6. error while loading shared libraries: libmysqlcppconn.so.7: cannot open shared object file: No such file or directory

    1. 即使libmysqlcppconn.so.7和与之相关存在,也报这个错误. 解决方法:临时添加LD_LIBRARY_PATH, 假使 libmysqlcppconn.so在/usr/local/ ...

  7. 使用 Nginx 和 Gunicorn 部署 Django 博客(转)

    原文:http://zmrenwu.com/post/20/  http://www.siar.me/post/9/ 针对很多朋友反映按照教程的做法始终只能看到 Nginx 欢迎页面的问题,Tian ...

  8. OpenStack API部分高可用配置(二)

    一.安装与配置HAProxy 1.调整内核参数,允许绑定VIP: vim /etc/sysctl.conf [内容] net.ipv4.ip_nonlocal_bind=1 sysctl -p 2.安 ...

  9. C语言复习---迭代法,牛顿迭代法,二分法求根

    一:用迭代法求 x=√a.求平方根的迭代公式为:X(n+1)=(Xn+a/Xn) /2. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> ...

  10. django2.0 官方中文文档地址

    django2.0 官方开始发布中文文档了,之前还想着一直翻译完成所有有必要的内容,想着可以省事一些了,打开以后看了一下,发现官方的中文文档还没翻译完成, 现在(2018-7-10)最新章节是是  编 ...