牛客网暑期多校训练赛 第三场 C题 Shuffle Cards

2024-04-09 12:58

本文主要是介绍牛客网暑期多校训练赛 第三场 C题 Shuffle Cards,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接

 

题意:

有一堆卡牌,一开始是从1到n的序列放好,现在有M次操作。每次操作将从第Pi个卡牌开始往后拿出Si个卡牌放在剩余卡牌的上方。问最后序列是什么。

 

思路:

打完比赛的时候发现了大佬的解法,用了一个完全没听过的操作rope。代码几乎可以说是和string一样了,但是它的速度却是惊人的快,赶紧学起来!!!

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
rope<int> a;
int main()
{int n,q,l,r;scanf("%d%d",&n,&q);for(int i=1;i<=n;i++)a+=i;for(int i=1;i<=q;i++){scanf("%d%d",&l,&r);a=a.substr(l-1,r)+a.substr(0,l-1)+a.substr(l+r-1,n-(l+r-1)+1);}for(int i=0;i<n;i++){if(i!=n-1)printf("%d ",a[i]);elseprintf("%d\n",a[i]);}return 0;
}

 

正常的思路:

 

用一个平衡树来处理,这个操作,先将1~Pi+Si-1这个区间翻转。然后再将1~Si区间翻转,和Si+1~Pi+Si-1区间翻转就是最后的区间。这里学了一下fhqtreap,一个非旋转的treap代码比SPLAY好写很多。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
using namespace std;
const int maxn=1e5+5;
struct node
{int son[2],v,rnd,size;int fz;
}tr[maxn];
int n,m,l,r;
int tot,root;
int new_node(int v)//创建权值为v的结点。
{tot++;tr[tot].size=1;tr[tot].v=v;tr[tot].rnd=rand();tr[tot].fz=tr[tot].son[0]=tr[tot].son[1]=0;return tot;
}
void update(int x)
{tr[x].size=tr[tr[x].son[0]].size+tr[tr[x].son[1]].size+1;if(x&&tr[x].fz){tr[tr[x].son[0]].fz^=1;tr[tr[x].son[1]].fz^=1;swap(tr[x].son[0],tr[x].son[1]);tr[x].fz^=1;}
}
int build(int l,int r)
{if(l>r) return 0;int mid=(l+r)/2;int v=mid-1;int now=new_node(v);tr[now].son[0]=build(l,mid-1);tr[now].son[1]=build(mid+1,r);update(now);return now;
}
int merge(int x,int y)
{if(!x||!y)return x+y;update(x),update(y);if(tr[x].rnd<tr[y].rnd){tr[x].son[1]=merge(tr[x].son[1],y);update(x);return x;}else{tr[y].son[0]=merge(x,tr[y].son[0]);update(y);return y;}
}void split(int now,int k,int &x,int &y)//按照节点个数分离,把节点个数小于k的分给x,大于等于的分给y
{if(!now)x=y=0;else{update(now);if(k<=tr[tr[now].son[0]].size)y=now,split(tr[now].son[0],k,x,tr[now].son[0]);elsex=now,split(tr[now].son[1],k-tr[tr[now].son[0]].size-1,tr[now].son[1],y);update(now);}
}void rev(int l,int r)
{int x,y,u,v;split(root,r+1,x,y);split(x,l,u,v);tr[v].fz^=1;root=merge(merge(u,v),y);
}
void print(int now)
{if(!now)return;update(now);print(tr[now].son[0]);if(tr[now].v>=1&&tr[now].v<=n)printf("%d ",tr[now].v);print(tr[now].son[1]);
}
int main()
{srand((unsigned)time(NULL));scanf("%d%d",&n,&m);root=build(1,n+2);for(int i=1;i<=m;i++){scanf("%d%d",&l,&r);rev(1,l+r-1);rev(1,r);rev(r+1,l+r-1);}print(root);return 0;
}

 

这篇关于牛客网暑期多校训练赛 第三场 C题 Shuffle Cards的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/888209

相关文章

poj 1511 Invitation Cards(spfa最短路)

题意是给你点与点之间的距离,求来回到点1的最短路中的边权和。 因为边很大,不能用原来的dijkstra什么的,所以用spfa来做。并且注意要用long long int 来存储。 稍微改了一下学长的模板。 stack stl 实现代码: #include<stdio.h>#include<stack>using namespace std;const int M

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

暑期学习总结

iOS学习 前言无限轮播图换头像网络请求按钮的configuration属性总结 前言 经过暑期培训,完成了五个项目的仿写,在项目中将零散的内容经过实践学习,有了不少收获,因此来总结一下比较重要的内容。 无限轮播图 这是写项目的第一个难点,在很多项目中都有使用,越写越熟练。 原理为制造两个假页,在首和尾分别制作最后一页和第一页的假页,当移动到假页时,使用取消动画的方式跳到

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

CPC23第三场、第四场总结

这两天跟着Arthur学长们混了两天现场赛,有种打怪升级的感觉,就是90级的老大们带30级的我去打100级的BOSS,看着Arthur他们在不断的输出,我在一旁水经验·······不过我也没闲着玩泥巴,在status里留下了一大片WA、TLE、RE··········         CPC23第三场,开场19分钟,Arthur全场一A了C题,于是我就开始跟着切C题。看了一眼题目

2015多校联合训练第三场Work(hdu5326)

题意: a是b的上司,b是c的上司,则a是c的上司,问构成一个树种,有多人是 k个人的上司 思路: 先找出root,然后dfs一下就行 #include <bits/stdc++.h>#define LL long longusing namespace std;const int MAXN = 1e6;int f[105];int n, k;int mp[101][101];

2015年多校联合训练第三场RGCDQ(hdu5317)

题意: f(i)代表i数中有的素数的种数,给出区间[l,r],求区间内max(gcd(f(i))), 由于i最大是1e6,2*3*5*7*11*13*17>1e6,故最多不超过7种素数, 先打表打出1e6内的素数种数表,然后用sum[i][j]代表1-i个数中,还有j个素数的个数,最后用sum[r][j] - sum[l-1][j]求出区间内含有j个素数的数的个数,暴力找出1,2,3,4,5

2015多校联合训练第一场Tricks Device(hdu5294)

题意:给一个无向图,给起点s,终点t,求最少拆掉几条边使得s到不了t,最多拆几条边使得s能到t 思路: 先跑一边最短路,记录最短路中最短的边数,总边数-最短边数就是第二个答案 第一个答案就是在最短路里面求最小割,也就是求最大流,然后根据最短路在建个新图,权为1,跑一边网络流 模板题,以后就用这套模板了 #include <iostream>#include <cstdio>#incl