ABC260 A~F

  • [A - A Unique Letter](https://atcoder.jp/contests/abc260/tasks/abc260_a)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
  • [B - Better Students Are Needed!](https://atcoder.jp/contests/abc260/tasks/abc260_b)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
      • 代码1
      • 代码2
  • [C - Changing Jewels](https://atcoder.jp/contests/abc260/tasks/abc260_c)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
  • [D - Draw Your Cards](https://atcoder.jp/contests/abc260/tasks/abc260_d)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
  • [E - At Least One](https://atcoder.jp/contests/abc260/tasks/abc260_e)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
  • [F - Find 4-cycle](https://atcoder.jp/contests/abc260/tasks/abc260_f)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码

A - A Unique Letter

题目大意

给定一个长度为333的字符串SSS。
输出SSS中出现正好一次的字母(任意,如abc中,三个字母都可为答案)。

如果没有,输出-1

数据保证SSS的长为333,且由小写英文字母组成。

输入格式

SSS

输出格式

输出任意符合条件的答案。

样例

SSS 输出
pop o
abc a/b/c
xxx -1

分析

我们设输入的3个字母分别为abc
首先,如果a=b=ca=b=ca=b=c,那么输出−1-1−1。
其次,我们依次尝试找到两个相同的字母:

  • xxy形式(a=ba=ba=b):输出ccc
  • xyx形式(a=ca=ca=c):输出bbb
  • yxx形式(b=cb=cb=c):输出aaa
  • xyz形式(a≠b≠ca\ne b\ne ca=b=c):输出任意一个

代码

这里,我把最后两种情况合并了(一个else搞定,都输出aaa):

#include <cstdio>
using namespace std;int main()
{char a = getchar(), b = getchar(), c = getchar();if(a == b && b == c) puts("-1");else if(a == c) putchar(b);else if(a == b) putchar(c);else putchar(a);return 0;
}

B - Better Students Are Needed!

题目大意

NNN个员工参加了一场选聘考试。
第iii个员工数学考了AiA_iAi​分,英语BiB_iBi​分。

公司按如下的方式选聘员工:

  1. 数学分数在前XXX的被直接录取;
  2. 剩下的人中,英语分数在前YYY的被录取;
  3. 最后,总分在前ZZZ的被录取,剩下的人被淘汰。

注意:分数相同的员工按编号排序。

输出被录取的所有员工的编号,按升序排列。

1≤N≤10001\le N\le 10001≤N≤1000
0≤X,Y,Z≤N0\le X,Y,Z\le N0≤X,Y,Z≤N
1≤X+Y+Z≤N1\le X+Y+Z\le N1≤X+Y+Z≤N
0≤Ai,Bi≤1000\le A_i,B_i\le 1000≤Ai​,Bi​≤100

输入格式

NXYZN~X~Y~ZN X Y Z
A1A2…ANA_1~A_2~\dots~A_NA1​ A2​ … AN​
B1B2…BNB_1~B_2~\dots~B_NB1​ B2​ … BN​

输出格式

输出被录取的所有员工的编号,按升序排列,每行一个。

样例

略,请自行前往AtCoder查看

分析

本题主要有两种思路:

  1. pair<int, int>代表一个员工,再使用vector+sortpriority_queue执行三次分别排序数学、英语、总分;
  2. struct { int math, english, id; }表示员工,存储一次,排序三次(使用不同的排序依据)

详见代码1、代码2。

代码

代码1

  • vector+sort实现

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #define maxn 1005
    using namespace std;int a[maxn], b[maxn];
    bool used[maxn];int main()
    {int n, x, y, z;scanf("%d%d%d%d", &n, &x, &y, &z);for(int i=0; i<n; i++)scanf("%d", a + i);for(int i=0; i<n; i++)scanf("%d", b + i);// Mathvector<pair<int, int>> sel_a;for(int i=0; i<n; i++)sel_a.emplace_back(-a[i], i);sort(sel_a.begin(), sel_a.end());for(int i=0; i<x; i++)used[sel_a[i].second] = true;// Englishvector<pair<int, int>> sel_b;for(int i=0; i<n; i++)if(!used[i])sel_b.emplace_back(-b[i], i);sort(sel_b.begin(), sel_b.end());for(int i=0; i<y; i++)used[sel_b[i].second] = true;// Totalvector<pair<int, int>> sel_t;for(int i=0; i<n; i++)if(!used[i])sel_t.emplace_back(-(a[i] + b[i]), i);sort(sel_t.begin(), sel_t.end());for(int i=0; i<z; i++)used[sel_t[i].second] = true;for(int i=0; i<n; i++)if(used[i])printf("%d\n", i + 1);return 0;
    }
    
  • priority_queue实现
    #include <cstdio>
    #include <queue>
    #define maxn 1005
    using namespace std;int a[maxn], b[maxn], c[maxn];
    bool used[maxn];inline void selectOnce(int* scores, int n, int snum)
    {priority_queue<pair<int, int>> sel;for(int i=0; i<n; i++)if(!used[i]){sel.emplace(-scores[i], i);if(sel.size() > snum) sel.pop();}while(!sel.empty())used[sel.top().second] = true, sel.pop();
    }int main()
    {int n, x, y, z;scanf("%d%d%d%d", &n, &x, &y, &z);for(int i=0; i<n; i++)scanf("%d", a + i);for(int i=0; i<n; i++)scanf("%d", b + i);for(int i=0; i<n; i++)c[i] = a[i] + b[i];selectOnce(a, n, x);selectOnce(b, n, y);selectOnce(c, n, z);for(int i=0; i<n; i++)if(used[i])printf("%d\n", i + 1);return 0;
    }
    

代码2

#include <cstdio>
#include <vector>
#include <algorithm>
#define maxn 1005
using namespace std;struct Emp { // Employeeint math, eng, id;
} emps[maxn];inline bool cmp1(const Emp& e1, const Emp& e2) {return e1.math == e2.math?e1.id < e2.id:e1.math > e2.math;
}inline bool cmp2(const Emp& e1, const Emp& e2) {return e1.eng == e2.eng?e1.id < e2.id:e1.eng > e2.eng;
}inline bool cmp3(const Emp& e1, const Emp& e2) {int tot1 = e1.math + e1.eng, tot2 = e2.eng + e2.math;return tot1 == tot2?e1.id < e2.id:tot1 > tot2;
}inline bool cmp4(const Emp& e1, const Emp& e2) {return e1.id < e2.id;
}int main()
{// Inputint n, x, y, z;scanf("%d%d%d%d", &n, &x, &y, &z);for(int i=0; i<n; i++)scanf("%d", &emps[i].math),emps[i].id = i;for(int i=0; i<n; i++)scanf("%d", &emps[i].eng);// Sortauto last = emps + n;sort(emps, last, cmp1);sort(emps + x, last, cmp2);sort(emps + x + y, last, cmp3);sort(emps, emps + x + y + z, cmp4); // 按编号升序排序// Outputfor(int i=0; i<x+y+z; i++)printf("%d\n", emps[i].id + 1);return 0;
}

C - Changing Jewels

题目大意

Takahashi有一个NNN级的红色宝石。
他可以重复下列操作任意次数:

  • 将一个NNN级的红色宝石转换为“一个(N−1)(N-1)(N−1)级的红色宝石和XXX个NNN级的蓝色宝石”。
  • 将一个NNN级的蓝色宝石转换为“一个(N−1)(N-1)(N−1)级的红色宝石和YYY个N−1N-1N−1级的蓝色宝石”。

Takahashi最后最多能得到几个111级的蓝色宝石?

1≤N≤101\le N\le 101≤N≤10
1≤X,Y≤51\le X,Y\le 51≤X,Y≤5

输入格式

NXYN~X~YN X Y

输出格式

输出一个整数,即最终蓝色宝石的数量。

样例

NNN XXX YYY 输出
222 333 444 121212
101010 555 555 394234990039423499003942349900

注意小心323232位整数(int/int32)溢出。

分析

要获得(N−1)(N-1)(N−1)级的蓝宝石,必须先尽可能多的获得NNN级的蓝宝石。
而要达到这个目的,就需要有尽可能多的NNN级红宝石。

以此类推,我们可以按顺序进行操作111,操作222……直到所有宝石全部为111级(也就是循环(N−1)(N-1)(N−1)次)。维护两个变量red\text{red}red(初始为111)和blue\text{blue}blue(初始为000),分别表示当前的红、蓝宝石的数目。
每次循环,先将blue\text{blue}blue加上red×X\text{red}\times Xred×X(操作111),再将red\text{red}red加上blue\text{blue}blue、blue\text{blue}blue乘上YYY(操作222)。

时间复杂度O(n)\mathcal O(n)O(n),如有读不懂的地方,可参考代码。

代码

注意使用long long

#include <cstdio>
using namespace std;int main()
{int n, x, y;scanf("%d%d%d", &n, &x, &y);long long red = 1LL, blue = 0LL;while(--n){blue += red * x;red += blue, blue *= y;}printf("%lld\n", blue);return 0;
}

D - Draw Your Cards

题目大意

有NNN张牌,上面分别写着数字P1,P2,…,PNP_1,P_2,\dots,P_NP1​,P2​,…,PN​。
按照这个顺序,我们进行NNN个操作,第iii个操作的具体步骤如下:

  • 取出第iii张牌,令X=PiX=P_iX=Pi​;
  • 找到存堆中顶牌≥X~\ge X ≥X的最小一张,将这张牌置于其上;
  • 如果没有符合条件的牌,将XXX放入一新堆;
  • 当某堆牌数达到KKK时,把这堆的牌全部吃掉。

求每张牌被吃掉的时间(若没有被吃掉,输出-1,详见输出格式)。

1≤K≤N≤2×1051\le K\le N \le 2\times 10^51≤K≤N≤2×105
PPP是(1,2,…,N)(1,2,\dots,N)(1,2,…,N)的一种排列。

输入格式

NKN~KN K
P1P2…PNP_1~P_2~\dots~P_NP1​ P2​ … PN​

输出格式

输出NNN行,第iii行表示卡片iii被吃掉的时间(如果没被吃掉,输出-1)。

样例

略,就是懒

分析

首先肯定不能用vector<stack<int>>这种数据结构,效率太低,容易写错,还不好用。可以用一个类似于并查集的数据结构,每次叠放操作都可看作“把下面的牌的父亲设置为上面的牌”。我们还需要记录并查集中每个连通分量的大小,方便模拟“吃掉”操作。

最终对于每个节点,输出其祖宗被吃掉的时间(咋听起来有点怪)。

目前的时间复杂度是O(N2)\mathcal O(N^2)O(N2),因为每次操作都需要用O(n)\mathcal O(n)O(n)的时间,找到最小的符合条件的牌堆。
很容易想到,可以使用set优化。

set是自动排序的集合,常用的的操作有插入(insert)、删除(erase)、二分查找(lower_bound/upper_bound),一次操作的时间复杂度均为O(log⁡n)\mathcal O(\log n)O(logn)。

这时,使用一个set<int>维护每个堆顶的卡牌编号,就可以把时间复杂度降到O(nlog⁡n)\mathcal O(n\log n)O(nlogn)以内。

至此,此题完。注意对K=1K=1K=1的特判。

代码

#include <cstdio>
#include <set>
#define maxn 200005
using namespace std;int fa[maxn], eat[maxn], sz[maxn];int find(int x) {return fa[x] == x? x: fa[x] = find(fa[x]);
}int main()
{int n, k;scanf("%d%d", &n, &k);set<int> cards;for(int i=0; i<n; i++){int x;scanf("%d", &x);x --;eat[x] = -1, fa[x] = x;if(k == 1){eat[x] = i + 1;continue;}auto it = cards.upper_bound(x);if(it == cards.end())cards.insert(x), sz[x] = 1;else{fa[*it] = x;cards.erase(it);if((sz[x] = sz[*it] + 1) == k)eat[x] = i + 1;else cards.insert(x);}}for(int i=0; i<n; i++)printf("%d\n", eat[find(i)]);return 0;
}

E - At Least One

题目大意

给定整数MMM和NNN对整数:(A1,B1),(A2,B2),…,(AN,BN)(A_1,B_1),(A_2,B_2),\dots,(A_N,B_N)(A1​,B1​),(A2​,B2​),…,(AN​,BN​)。
题目保证对于任意iii,1≤Ai<Bi≤M1\le A_i<B_i\le M1≤Ai​<Bi​≤M。

符合如下条件的整数序列SSS被称作好的序列

  • SSS是(1,2,…,M)(1,2,\dots,M)(1,2,…,M)的连续子序列;
  • 对于每个iii,SSS中包含AiA_iAi​或BiB_iBi​(或同时包含)。

令f(k)=(f(k)=(f(k)=(长为kkk的好序列的个数)))。求f(1),f(2),…,f(M)f(1),f(2),\dots,f(M)f(1),f(2),…,f(M)。

1≤N≤2×1051\le N\le 2\times 10^51≤N≤2×105
2≤M≤2×1052\le M\le 2\times 10^52≤M≤2×105
1≤Ai<Bi≤M1\le A_i<B_i\le M1≤Ai​<Bi​≤M

输入格式

NMN~MN M
A1B1A_1~B_1A1​ B1​
A2B2A_2~B_2A2​ B2​
⋮\vdots⋮
ANBNA_N~B_NAN​ BN​

输出格式

输出一行,即f(1),f(2),…,f(M)f(1),f(2),\dots,f(M)f(1),f(2),…,f(M),用空格分隔。

样例

略,请自行前往AtCoder查看

分析

首先,根据题意,SSS可被表示为一个区间[l,r][l,r][l,r],其中1≤l≤r≤M1\le l\le r\le M1≤l≤r≤M。
当对于每个iii,l≤Ai≤rl\le A_i\le rl≤Ai​≤r或l≤Bi≤rl\le B_i\le rl≤Bi​≤r时,区间[l,r][l,r][l,r]符合条件。
若按这样直接暴力枚举,时间复杂度为O(N2M)\mathcal O(N^2M)O(N2M),明显超时,不可取。

仔细想想会发现,对于两个区间[l,r][l,r][l,r]和[a,b][a,b][a,b],若a≤l≤r≤ba\le l\le r\le ba≤l≤r≤b,且[l,r][l,r][l,r]符合条件,则[a,b][a,b][a,b]也肯定符合条件。

此时,可以考虑使用滑动窗口优化,则时间复杂度降至O(MN)\mathcal O(MN)O(MN)。

继续优化。在窗口滑动的过程中,每次移动左/右端点时考虑一次移动对当前符合条件的iii的数量的贡献,需要两个数组cnt[N]\mathrm{cnt}[N]cnt[N](记录每个AiA_iAi​和BiB_iBi​符合条件的个数)和inv[M+1][…]\mathrm{inv}[M+1][\dots]inv[M+1][…](预处理每个数值对应的所有元素下标)。

总时间复杂度为O(N+M)\mathcal O(N+M)O(N+M),详见代码。

代码

#include <cstdio>
#include <vector>
#define maxn 200005
using namespace std;vector<int> inv[maxn];
int cnt[maxn], ans[maxn];int main()
{int n, m;scanf("%d%d", &n, &m);for(int i=0; i<n; i++){int a, b;scanf("%d%d", &a, &b);inv[a].push_back(i);inv[b].push_back(i);}int left = n;for(int i=1, j=1; i<=m; i++){for(; j <= m && left > 0; j++)for(int x: inv[j])if(++cnt[x] == 1)left --;if(left > 0) break;ans[j - i] ++, ans[m - i + 2] --;for(int x: inv[i])if(--cnt[x] == 0)left ++;}for(int i=1; i<=m; i++)printf("%d ", ans[i] += ans[i - 1]);return 0;
}

F - Find 4-cycle

题目大意

给定一个二分图GGG,形如下:

图片来源:二分图_百度百科

其中顶点集UUU中的顶点数为SSS,VVV的顶点数为TTT,总边数为MMM(第iii条边连接uiu_iui​和viv_ivi​)。
请找出此图中任意长为444的环。如果没有,输出-1

2≤S≤3×1052\le S\le 3\times 10^52≤S≤3×105
2≤T≤30002\le T\le 30002≤T≤3000
4≤M≤min⁡(S×T,3×105)4\le M\le \min(S\times T,3\times 10^5)4≤M≤min(S×T,3×105)
1≤ui≤S<vi≤S+T1\le u_i\le S<v_i\le S+T1≤ui​≤S<vi​≤S+T

输入格式

STMS~T~MS T M
u1V1u_1~V_1u1​ V1​
u2V2u_2~V_2u2​ V2​
⋮\vdots⋮
uMVMu_M~V_MuM​ VM​

输出格式

如果有长为444的环,输出其中四个顶点的编号(顺序随意,用空格分隔)。
如果没有,输出-1

样例

略,请自行前往AtCoder查看

分析

注意到样例中TTT只有300030003000,O(T2)=9×106\mathcal O(T^2)=9\times 10^6O(T2)=9×106可以接受。
然后因为是二分图,所以长为444的环肯定是在两个顶点集中各有两个点。

令f(x,y)f(x,y)f(x,y)为目前发现的与点x,yx,yx,y都相连的点,初始化为−1-1−1(表示未发现)。
输入使用邻接表存储,G[v]G[v]G[v]存储连到vvv的所有点,注意只需存顶点集UUU的G[v]G[v]G[v]即可。
再对于每个vvv,依次枚举G[v]G[v]G[v]中的两个点(x,y)(x,y)(x,y),如果f(x,y)=−1f(x,y)=-1f(x,y)=−1,则执行f(x,y):=vf(x,y):=vf(x,y):=v,如果不是−1-1−1,则输出{x} {y} {v} {f(x,y)},结束程序。

时间复杂度约为O(T2)\mathcal O(T^2)O(T2)。

本题中的时间复杂度怎么算?
→f(x,y)\to f(x,y)→f(x,y)中不同(x,y)(x,y)(x,y)的组合只有T(T−1)=T2−T≈T2T(T-1)=T^2-T\approx T^2T(T−1)=T2−T≈T2种。
→\to~→  根据鸽笼原理(又称抽屉原理),在最坏情况下,T2T^2T2种组合都记录过fff之后,下一种组合无论是什么肯定都已经记录过fff,因此最坏时间复杂度为O(T2)\mathcal O(T^2)O(T2),对于随机数据的平均时间复杂度远远小于这个值。

代码

#include <cstdio>
#include <cstring>
#include <vector>
#define maxs 300005
#define maxt 3005
using namespace std;vector<int> G[maxs];
int f[maxt][maxt];int main()
{int s, t, m;scanf("%d%d%d", &s, &t, &m);while(m--){int u, v;scanf("%d%d", &u, &v);G[--u].push_back(--v - s);}memset(f, -1, sizeof(f));for(int i=0; i<s; i++)for(int j=0; j+1<G[i].size(); j++)for(int k=j+1; k<G[i].size(); k++){int u = G[i][j], v = G[i][k];if(u > v) u ^= v ^= u ^= v;if(f[u][v] != -1){printf("%d %d %d %d\n", f[u][v] + 1, i + 1, u + s + 1, v + s + 1);return 0;}f[u][v] = i;}puts("-1");return 0;
}

AtCoder Beginner Contest 260 A~F 题解相关推荐

  1. AtCoder Beginner Contest 244 D~F 题解

    ABC244 D~F [D - Swap Hats](https://atcoder.jp/contests/abc244/tasks/abc244_d) 题目大意 输入格式 输出格式 样例 样例输入 ...

  2. AtCoder Beginner Contest 246 A~E 题解 Bishop 2

    AtCoder Beginner Contest 246 A~E 题解 A Four Points 题意 给你矩形的三个顶点,输出剩下那个 思路 把横坐标和纵坐标分开,必会存在两个相同的数,横纵坐标就 ...

  3. AtCoder Beginner Contest 252 A~G 题解

    前言 这是我第一次写7题(A~G)的ABC题解,若有写得不好或者不到位的地方请多多指教,我将万分感激,感谢大家的支持! ABC252 A~G [A - ASCII code](https://atco ...

  4. AtCoder Beginner Contest 196 A~E题解

    ABC196 A~E [A - Difference Max](https://atcoder.jp/contests/abc196/tasks/abc196_a) 题目大意 输入格式 输出格式 样例 ...

  5. AtCoder Beginner Contest 242 C~E 题解

    ABC242 C~E [C - 1111gal password](https://atcoder.jp/contests/abc242/tasks/abc242_c) 题目大意 输入格式 输出格式 ...

  6. AtCoder Beginner Contest 192 A~D题解

    ABC192 A~D [A - Star](https://atcoder.jp/contests/abc192/tasks/abc192_a) 题目大意 输入格式 输出格式 样例 分析 代码 [B ...

  7. AtCoder Beginner Contest 205 A~E 题解

    ABC205 A~E [A - kcal](https://atcoder.jp/contests/abc205/tasks/abc205_a) 题目大意 输入格式 输出格式 样例 分析 代码 [B ...

  8. KYOCERA Programming Contest 2021 (AtCoder Beginner Contest 200) A~E 题解

    ABC200/KYOCERA2021 A~E [A - Century](https://atcoder.jp/contests/abc200/tasks/abc200_a) 题目大意 输入格式 输出 ...

  9. Mynavi Programming Contest 2021 (AtCoder Beginner Contest 201) A~E 题解

    ABC201/Mynavi2021 A~E [A - Tiny Arithmetic Sequence](https://atcoder.jp/contests/abc201/tasks/abc201 ...

最新文章

  1. Blend_ControlTemplate(Z)
  2. caffe 问题集锦之使用cmake编译多GPU时,更改USE_NCCL=1无效
  3. Exchange2007中创建收件人对象、通讯组和地址列表和客户端访问
  4. 互联网通用架构技术----缓存雪崩
  5. 《JavaWeb从入门到改行》注册时向指定邮箱发送邮件激活
  6. Android自定义事件总线,android事件总线EventBus3.0使用方法详解
  7. 计算机毕设分词,毕业设计(论文)+计算机科学与技术+中文分词方法研究与实现论文全文.doc...
  8. 【C#】WM 消息大全
  9. Affine层/Softmax层的实现
  10. 2021大树分享收集的网盘搜索站给兄弟们
  11. 第九届蓝桥杯JavaC组省赛真题
  12. Eplan教程——如何使用项目检查功能
  13. 利用scrapy爬取美图录网站图集按模特姓名存储到本地(三)
  14. CAD等分不显示等分点
  15. 2021ICPC网络赛第一场【A Busiest Computing Nodes】【D Edge of Taixuan】
  16. webpack serve 配置问题TypeError: Class constructor ServeCommand cannot be invoked without ‘new‘
  17. 实体-关系联合抽取:Incremental Joint Extraction of Entity Mentions and Relations
  18. 3600000毫秒等于多少小时_工地扬尘监测规定-多少算超标?
  19. 看“三国”谈谁是好领导-超博好领导系列
  20. HTML5离线浏览再进一步

热门文章

  1. vooc充电原理_OPPO VOOC充电技术详解
  2. 幻灯片效果+背景音乐
  3. 木其工作室代写程序 [原]java web项目各种乱码的解决方案
  4. 小程序推广方案有哪些?
  5. 实时数仓建设第2问:怎样使用flink sql快速无脑统计当天下单各流程(已发货,确认收货等等)状态的订单数量
  6. Oracle中模拟SQL中的isnull函数
  7. php 将信息 post 回给 paypal 进行验证出错,paypal升级的几个问题
  8. JS学习篇(一) JavaScript语言特性
  9. 文档关键词维护,文章页自动添加关键词内链锚文本-织梦(Dedecms)
  10. 联想一直提示正在更新计算机启动配置,联想笔记本开机页面一直停留在准备配置windows 请勿关闭计算机 也没有以...