暑期训练 CF套题
题意:有n个数,都是0或1,然后必须执行一次操作,翻转一个区间,里面的数0变1,1变0,求最多1的数量
思路:最开始我写的最大字段和,后面好像写搓了,然后我又改成暴力,因为这个范围只有100,写n^3都没事,所以我们第一层枚举左区间,第二层枚举右区间,然后我们第三层记录左边1的数量,中间的0的数量,右边的1的数量即可
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll a[],num,n;
int main(){
scanf("%lld",&n);
for(int i=;i<=n;i++){
scanf("%lld",&a[i]);
}
ll mx=;
for(int i=;i<=n;i++){
for(int j=i;j<=n;j++){
ll shu=;
for(int k=;k<i;k++){
if(a[k]) shu++;
}
for(int k=i;k<=j;k++){
if(a[k]==) shu++;
}
for(int k=j+;k<=n;k++){
if(a[k]) shu++;
}
mx=max(shu,mx);
}
}
printf("%lld",mx);
}
题意:有n架飞机,现在因为一些原因飞机都只能拖延到k+1时刻后出发,一个时刻只能出发一架,每架飞机有个晚飞一分钟损失多少,最开始飞机是按顺序安排的时刻表,现在问你怎么排表损失最小
思路:首先我们知道最开始是 1 2 3 4 5,如果k为2,那么我们只能是 3 4 5 6 7 ,但是我们要怎么安排呢,我们能清晰的知道,每个人都是一分钟损耗多少,所以我们肯定是让最大的尽量少损失,因为差值都是固定的 3 4 5 6 7 - 1 2 3 4 5 差值和为10 ,只是我们现在要排列把这个差值给哪些数,我们肯定把差值尽量给损失小的,所以我们排个序,我们找最接近当前数的值,但是我们找又是个问题,一个只能用一次,用完就要删除,而且我们不能遍历找,符合这些要求的有个很好的东西就是 set,我们可以利用log级别的删除,set.lower_bound log级别的查找就能很好解决这个事
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define maxn 300005
#define mod 1000000007
using namespace std;
typedef long long ll;
struct sss
{
ll id;
ll x;
}a[maxn];
ll n,m;
ll vis[maxn];
set<ll> q;
int cmp(struct sss x,struct sss y){
return x.x>y.x;
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++){
q.insert(i+m);
}
for(int i=;i<=n;i++){
scanf("%lld",&a[i].x);
a[i].id=i;
}
sort(a+,a+n+,cmp);
ll sum=;
for(int i=;i<=n;i++){
ll x=*q.lower_bound(a[i].id);
//set<ll>::iterator t1=q.upper_bound(a[i].x);
sum+=(x-a[i].id)*a[i].x;
vis[a[i].id]=x;
q.erase(x);
}
printf("%lld\n",sum);
for(int i=;i<=n;i++){
printf("%lld ",vis[i]);
}
}
题意:有两个人玩石头剪刀布,最开始两个人会选择出什么,然后两个人都会根据对方和自己现在出的东西而改变下次出的,然后会进行k轮游戏,输出每个人赢得次数
思路:这个k特别大,但是情况最多有9种,也就是说9种过后必定会出现重复的,这个时候说明有循环节,我们把中间周期除掉计算即可
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define maxn 300005
#define mod 1000000007
using namespace std;
typedef long long ll;
struct sss
{
ll sum1,sum2;
}c[maxn];//记录当前步的比赛状况
ll A[][];
ll B[][];
ll vis[][];
ll chuan(ll a,ll b){
if(a==b) return ;
if(a==&&b==) return -;
if(a==&&b==) return ;
if(a==&&b==) return -;
if(a==&&b==) return ;
if(a==&&b==) return ;
if(a==&&b==) return -;
}
int main(){
ll k,a,b;
scanf("%lld%lld%lld",&k,&a,&b);
for(int i=;i<=;i++){
for(int j=;j<=;j++){
scanf("%lld",&A[i][j]);
vis[i][j]=-;
}
}
for(int i=;i<=;i++){
for(int j=;j<=;j++){
scanf("%lld",&B[i][j]);
}
}
ll sum1=,sum2=;
ll z=,flag=;
while(z<k){
ll w=chuan(a,b);
if(w==) sum1++;
else if(w==-) sum2++;
if(vis[a][b]!=-){//找到循环节
ll len=z-vis[a][b];
ll sy=k-z-;
sum1+=sy/len*(sum1-c[vis[a][b]].sum1);
sum2+=sy/len*(sum2-c[vis[a][b]].sum2);
sy%=len;
k=sy;
flag=;
ll a1=a,b1=b;
a=A[a1][b1];
b=B[a1][b1];
break;
}
c[z].sum1=sum1;
c[z].sum2=sum2;
vis[a][b]=z;
ll a1=a,b1=b;
a=A[a1][b1];
b=B[a1][b1];
z++;
}
z=;
while(flag&&z<k){
ll w=chuan(a,b);
if(w==) sum1++;
else if(w==-) sum2++;
ll a1=a,b1=b;
a=A[a1][b1];
b=B[a1][b1];
z++;
}
printf("%lld %lld",sum1,sum2);
}
题意:最开始有n个人,每个人会选择一个团队,自身带一个价值,然后下面有q次查询,说明这次比拼哪些团队不会参加,然后选获胜团队以及获胜团队里面最低能战胜其他所有人的人的价值
思路:我们首先用vector记录所以人的值,这肯定要做的,然后我们会发现我们要战胜肯定是要把其他所有人的最大值战胜,所以我们用一个set记录所有团队的最大值,我们缺席的话直接暴力
在set里面删除,然后我们再找出当前最大,那就是获胜者,然后找出次大,然后在获胜者团队二分找出正好比他大的值即可
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<set>
#include<utility>
#include<algorithm>
using namespace std;
#define mp make_pair
#define X first
#define Y second
const int N=;
int n,m,q,a[N],b[N];
int ban[N],c[N];
set<int>d[N];
pair<int,int>e[N];
int main(void)
{
int i,p1,p2;
scanf("%d",&n);
for(i=;i<=n;i++){scanf("%d%d",&p1,&p2);b[p1]=p2;d[p1].insert(p2);}
for(i=;i<=n;i++)e[i]=mp(b[i],i);
sort(e+,e++n);
scanf("%d",&q);
while(q--)
{
scanf("%d",&m);
for(i=;i<=m;i++){scanf("%d",c+i);ban[c[i]]=;}
p1=p2=;
for(i=n;i>=;i--)
{
if(==e[i].X)break;
if(ban[e[i].Y])continue;
if(p1){p2=e[i].Y;break;}
else p1=e[i].Y;
}
if(p1==)printf("0 0\n");
else if(p2==)printf("%d %d\n",p1,*d[p1].begin());
else printf("%d %d\n",p1,*d[p1].lower_bound(*(--d[p2].end())));
for(i=;i<=m;i++)ban[c[i]]=;
}
return ;
}
题意:开始有 n个数,然后如果有相同的连续的数x我们要合并,合并之后之前两个数删除然后插入x+1,然后直到不能再合并,下标是左边那个的下标,输出最后结果
思路:我们会发现合并必须要从低到高执行,因为新插入的是x+1,所以我们必须从低到高,然后我们要考虑的问题是,合并后,但是我的数组其实还是一样的位置,比如 1 1 2,我合并第 1 2个数数组里面就会变成 2 0 2 ,0代表这个位置没数了,但是我们下次合并又要怎么知道1 3个数可以合并呢,暴力肯定不现实,这个时候我们又会发现其实每个数也就和他的下个数有关,我们想用删除一个数,又要查询两个数是否相连,有个很适合这个结构,那就是链表,我们清晰的记录下一个下标是谁,然后上面我们合并后又要插入进去,那肯定是使用优先队列了,然后我们相等的值按下标排序,如果当前两个数不匹配,那么说前面这个数的位置肯定确定下来了。因为要么是下标不符合,中间隔了数,肯定不能再合并。要么是值不相等。从低到高,已经没别的合并的机会了
#include<cstdio>
#include<cmath>
#include<queue>
#include<iostream>
#include<algorithm>
#define maxn 200005
#define mod 1000000007
using namespace std;
typedef long long ll;
struct sss{
ll id;
ll next;
friend bool operator <(struct sss x,struct sss y){
if(x.next==y.next){
return x.id>y.id;
}
return x.next>y.next;
}
}a[maxn];
ll n;
priority_queue<struct sss> q;
ll b[maxn],c[maxn];
int main(){
ll n;
cin>>n;
for(int i=;i<=n;i++){
a[i].id=i;
if(i!=n)
a[i].next=i+;
else a[i].next=-;
}
for(int i=;i<=n;i++){
cin>>b[i];
struct sss e;
e.id=i;
e.next=b[i];
q.push(e);
}
ll num=;
while(q.size()>=){
struct sss x,y;
x=q.top();q.pop();
y=q.top();q.pop();
if(a[x.id].next==y.id&&x.next==y.next){
x.next++;
a[x.id].next=a[y.id].next;
q.push(x);
num++;
}
else{
c[x.id]=x.next;
q.push(y);
}
}
if(!q.empty()){
struct sss x=q.top();q.pop();c[x.id]=x.next;
}
if(!q.empty()){
struct sss x=q.top();q.pop();c[x.id]=x.next;
}
cout<<n-num<<"\n";
for(int i=;i<=n;i++){
if(c[i]!=){
cout<<c[i]<<" ";
}
}
}
题意:给定N,M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的,然后是Q次操作,操作分为两种,一种是查询城市x所在的联通集合中,最长的路为多长。二是连接两个联通集合,采用联通之后最长路最短的方案,无环图。
思路:因为一开时的图是不可以改变的,所以一开始用dfs处理出各个联通集合,并且记录住最大值,然后就是Q次操作,用并查集维护,注意因为联通的时候要采用最长路径最短的方案,所以s的转移方程变为s = max(s, (s+1)/2 + (s0+1)/2 + 1),因为两个连通块都记录了树的直径,如果我们其中一条路径是 1-2-3-4-5-6-7,那么这个连通块我肯定选择4点连接,为什么呢,因为如果我选3,那么我就可以走3-4-5-6-7,很明显长度更大,那么最优的肯定是选择中间点,所以我们每次合并的时候就是 选择两个路径的中间点长度再加上新加的那条求一个max
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm> using namespace std;
const int maxn = * 1e5 + ;
int N, M, Q, f[maxn], s[maxn];
int root, ans, rec;
vector<int> g[maxn]; int getfar(int x) {
return f[x] == x ? x : f[x] = getfar(f[x]);
} void link (int u, int v) {
int x = getfar(u);
int y = getfar(v); if (x == y)
return; if (s[x] < s[y])
swap(s[x], s[y]); f[y] = x;
s[x] = max(s[x], (s[x] + ) / + (s[y] + ) / + );
} void dfs (int u, int p, int d) {
f[u] = root; if (d > ans) {
ans = d;
rec = u;
} for (int i = ; i < g[u].size(); i++) {
if (g[u][i] != p)
dfs(g[u][i], u, d+);
}
} int main () {
int type, u, v; scanf("%d%d%d", &N, &M, &Q);
for (int i = ; i <= N; i++) {
f[i] = i;
g[i].clear();
} for (int i = ; i < M; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
} for (int i = ; i <= N; i++) {
if (f[i] == i) {
root = rec = i;
ans = -;
dfs(i, , ); ans = -;
dfs(rec, , );
s[i] = ans;
}
} for (int i = ; i < Q; i++) {
scanf("%d", &type);
if (type == ) {
scanf("%d", &u);
v = getfar(u);
printf("%d\n", s[v]);
} else {
scanf("%d%d", &u, &v);
link(u, v);
}
}
return ;
}
暑期训练 CF套题的更多相关文章
- [CF套题] CF-1163
CF-1163 传送门 # Penalty A B1 B2 C1 C2 D E F 3 (483) 464 +0 0:06 +1 01:13 +3 01:12 + 01:57 + 01:56 A 第一 ...
- [CF套题] CF-1201
CF-1201 传送门 # = * A 500 B 1000 C 1500 D 2000 E1 2000 E2 1000 1 (2217) 1672 482 00:09 400 01:40 790 0 ...
- [小结] 中山纪念中学2018暑期训练小结(划掉)(颓废记)-Day10
[小结] 中山纪念中学2018暑期训练小结(划掉)(颓废记)-Day10 各位看众朋友们,你们好,今天是2018年08月14日,星期二,农历七月初四,欢迎阅看今天的颓废联编节目 最近发生的灵异事件有 ...
- Noip2019暑期训练2 反思
经过两次测试,通过深刻的反思,我主要发现了以下易犯错误: 1.做题目时过于追求速度,导致好几处代码都出现手误打错的现象!而且,千万不要图快.图方便就复制粘贴,非常容易出错!(例如T3-party中直接 ...
- 第46套题【STL】【贪心】【递推】【BFS 图】
已经有四套题没有写博客了.今天改的比较快,就有时间写.今天这套题是用的图片的形式,传上来不好看,就自己描述吧. 第一题:单词分类 题目大意:有n个单词(n<=10000),如果两个单词中每个字母 ...
- Educational Codeforces Round 15 套题
这套题最后一题不会,然后先放一下,最后一题应该是大数据结构题 A:求连续最长严格递增的的串,O(n)简单dp #include <cstdio> #include <cstdlib& ...
- 做了一道cf水题
被一道cf水题卡了半天的时间,主要原因时自己不熟悉c++stl库的函数,本来一个可以用库解决的问题,我用c语言模拟了那个函数半天,结果还超时了. 题意大概就是,给定n个数,查询k次,每次查询过后,输出 ...
- 【套题】qbxt国庆刷题班D1
Day1 事实上D1的题目还是比较简单的= =然而D1T2爆炸了就十分尴尬--错失一波键盘 看题 T1 传送门 Description 现在你手里有一个计算器,上面显示了一个数\(S\),这个计算器十 ...
- Moscow Pre-Finals Workshop 2016. Japanese School OI Team Selection. 套题详细解题报告
写在前面 谨以此篇题解致敬出题人! 真的期盼国内也能多出现一些这样质量的比赛啊.9道题中,没有一道凑数的题目,更没有码农题,任何一题拿出来都是为数不多的好题.可以说是这一年打过的题目质量最棒的五场比赛 ...
随机推荐
- 深信达加密下禁用IME
1.控制面板 2.管理工具 3.计算机管理 4.系统工具 5.任务计划程序 6.任务计划程序库 7.Microsoft 8.Windows 9.TextServicesFramework 10.MsC ...
- (经典文章uplink)Information capacity and power control in single-cell multiuser communications(1995)
摘要:本文在用户衰落被完美测量的情况下,提出一种可最大程度提高单小区多用户通信平坦衰落的信息容量的功率控制.主要特征为:在任何特定的时刻,只有一个用户在整个带宽上进行传输,并且在信道良好时为用户分配更 ...
- 最小生成树基础算法(Prim + Krustal)
最小生成树问题的引入: 对于一个无向图G(V, E),需要用图中的n - 1条边连接图中的n个顶点并且不产生回路所产生的树就叫做生成树,其中权值总和最小的就是最小生成树. 如何求解最小生成树问题: 譬 ...
- mysql DATETIME和TIMESTAMP类型
以mysql 5.7.20 为例 一直以来,理解有偏差,作此记录,纠正 一.DATETIME和TIMESTAMP 都有高达微秒(6位)的精度 范围 DATETIME 1000-01-01 00: ...
- 【五一qbxt】day6 OI中的stl
from:why 很多很多part…… 1.pair: 相当于把两个变量放在一起: #include<utility> using namespace std; pair<TypeN ...
- [暑假集训Day1T3]新的开始
新建一个虚拟节点后直接跑最小生成树即可,从虚拟节点往每个节点连的边权为每个点建发电站的代价,许多人的考场贪心策略是:先构建原图的最小生成树后找一个花费最小的地方建发电厂.但是这样做不对的地方在于:如果 ...
- Python自学第二天学习之《字符串与数字》
一.基本数据类型: 数字:int类型,不可变类型 格式 : a=10 1.其他类型转换成int型 : b=“123” c=int(b) #转换类型 print(c)----- 123 print(ty ...
- 2019 Multi-University Training Contest 1 - 1009 - String - 贪心
不知道错在哪里. 是要把atop改成stop!两个弄混了.感谢自造样例. #include<bits/stdc++.h> using namespace std; typedef long ...
- Codeforces 770C Online Courses In BSU (DFS)
<题目链接> 题目大意:给定$n$个任务,其中有$m$个主线任务,然后$n$个任务中,每个任务都有可能有一个list,表示完成这个任务之前必须要完成的任务,然后现在让你找出,完成这$m$个 ...
- JavaScript —— 字符串中使用正则表达式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...