2017.9.4模拟考试
a
【问题描述】
祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干
个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到
轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立
即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。
开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成
了过程记录的功能,而回放功能的实现则委托你来完成。
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做
的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。
【输入格式】
第一行是一个由大写字母’A’~’Z’组成的字符串,表示轨道上初始的珠子序列,
不同的字母表示不同的颜色。
第二行是一个数字��,表示整个回放过程共有��次操作。
接下来的��行依次对应于各次操作。每次操作由一个数字��和一个大写字母��
描述,以空格分隔。其中,��为新珠子的颜色。若插入前共有��颗珠子,则�� ∈ [0, ��]
表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。
【输出格式】
输出共��行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上
P57 a
第 3 页 共 8 页
的珠子序列。
如果轨道上已没有珠子,则以“-”表示。
【样例输入】
ACCBA
5
1 B
0 A
2 B
4 C
0 A
【样例输出】
ABCCBA
AABCCBA
AABBCCBA
-(这里本没有括号的,不打括号Markdown不显示短线)
A
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
100%的数据满足1 ≤ �� ≤ 103
, 1 ≤ �� ≤ 2 × 103。
模拟算法:模拟
strcpy大法好
我当时用的string模拟,不知道为什们炸掉了~~
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAXN = 200000;
char temp[MAXN],ch[MAXN];
int siz,pos,n;
bool ReMove(int p){
int head=p,last=p;
char k=ch[p];
while(head&&ch[head]==k) --head;
if(head||ch[head]!=k) ++head;
while(last<siz&&ch[last]==k) ++last;
if(last-head > 2){
strcpy(temp,ch+last);
strcpy(ch+head,temp);
siz=siz+head-last;
pos=head;
return 1;
}
else return 0;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
gets(ch); char c;
siz=strlen(ch);
scanf("%d",&n);
for(register int i=1;i<=n;++i){
scanf("%d %c",&pos,&c);
strcpy(temp,ch+pos);
strcpy(ch+pos+1,temp);//移动出一个空位来
ch[pos]=c,++siz;
while(ReMove(pos)&&siz) ReMove(pos);
if(siz) puts(ch);
else puts("-");
}
fclose(stdin);fclose(stdout);
return 0;
}
b
【问题描述】
栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借
助一个栈,依次将数组 1,3,2 按顺序入栈或出栈,可对其从大到小排序:
1 入栈;3 入栈;3 出栈;2 入栈;2 出栈;1 出栈。
在上面这个例子中,出栈序列是 3,2,1,因此实现了对数组的排序。
遗憾的是,有些时候,仅仅借助一个栈,不能实现对数组的完全排序。例如
给定数组 2,1,3,借助一个栈,能获得的字典序最大的出栈序列是 3,1,2:
2 入栈;1 入栈;3 入栈;3 出栈;1 出栈;2 出栈。
请你借助一个栈,对一个给定的数组按照出栈顺序进行从大到小排序。当无
法完全排序时,请输出字典序最大的出栈序列。
【输入格式】
输入共2行。
第一行包含一个整数��,表示入栈序列长度。
第二行包含��个整数,表示入栈序列。输入数据保证给定的序列是1到 n 的
全排列,即不会出现重复数字。
【输出格式】
仅一行,共��个整数,表示你计算出的出栈序列。
【样例输入】
3
2 1 3
【样例输出】
3 1 2
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于30%的数据,1 ≤ �� ≤ 103。
对于60%的数据,1 ≤ �� ≤ 105。
贪心+暴力模拟AC,不用考虑是否可以得到1-n的倒序排列,因为如果我们的求最大排列的算法做对了的话,能得到这种倒序排列,一定就会得到
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXN = 1e6+5;
int a[MAXN],n,top,maxx=-1e9;
stack<int> st;
inline void read(int &x){
x=0; int f=1; char c=getchar();
while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); } x*=f;
}
int main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
read(n);
for(register int i=1;i<=n;++i){
read(a[i]);
if(a[i]>maxx) maxx=a[i],top=i;
}
for(int i=1;i<=top;++i) st.push(a[i]);
printf("%d ",st.top());
st.pop();
maxx=-1e9;
int topc=0;
while(!st.empty()){
++top;
for(int j=top;j<=n;++j)
if(a[j]>maxx) maxx=a[j],topc=j;
while(!st.empty()&&st.top()>maxx){
printf("%d ",st.top());
st.pop();
}
for(int i=top;i<=topc;++i) st.push(a[i]);
top=topc,maxx=-1;
}
fclose(stdin);fclose(stdout);
return 0;
}
c
【问题描述】
小 Q 对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考
一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,小 Q 会在��轴正半轴和��轴正半轴分别挑选��个点。随后,他将��轴的
点与��轴的点一一连接,形成��条线段,并保证任意两条线段不相交。小 Q 确定
这种连接方式有且仅有一种。最后,小 Q 会给出��个询问。对于每个询问,将会
给定一个点��(����, ����),请回答线段 OP 与��条线段会产生多少个交点?
小 Q 找到了正在钻研数据结构的你,希望你可以帮他解决这道难题。
【输入格式】
第1行包含一个正整数��,表示线段的数量;
第2行包含��个正整数,表示小 Q 在��轴选取的点的横坐标;
第3行包含��个正整数,表示小 Q 在��轴选取的点的纵坐标;
第 4 行包含一个正整数��,表示询问数量;
随后��行,每行包含两个正整数����, ����,表示询问中给定的点的横、纵坐标。
【输出格式】
共��行,每行包含一个非负整数,表示你对这条询问给出的答案。
【样例输入】
3
4 5 3
3 5 4
2
1 1
3 3
【样例输出】
0
3
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于50%的数据,1 ≤ ��, ��, ≤ 2 × 103。
对于100%的数据,1 ≤ ��, �� ≤ 2 × 105,坐标范围≤ 108。
//先立个flag下次二分再写错就剁手
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2e5+100;
int px,py,n,x[MAXN],y[MAXN];
inline bool Judge(int k){
if(px==0){
if(py>=y[k]) return true;
else return false;
}
if(py==0){
if(px>=x[k]) return true;
else return false;
}
double pxx=px,x1=x[k],y2=y[k];
pxx=(x1-pxx)*y2/x1;
if(pxx<=(double)py) return true;
else return false;
}
inline void read(int &z){
z=0; int f=1; char c=getchar();
while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); }
while(c>='0'&&c<='9'){ z=z*10+c-'0'; c=getchar(); }
z*=f;
}
int solve(){
int l=0,r=n,ans=0;
while(l<=r){
int Mid=l+r>>1;
if(Judge(Mid)) l=Mid+1,ans=max(ans,Mid);
else r=Mid-1;
}
return ans;
}
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
int m; read(n);
for(int i=1;i<=n;++i) read(x[i]);
for(int i=1;i<=n;++i) read(y[i]);
sort(x+1,x+n+1);sort(y+1,y+1+n);
n++;
y[n]=x[n]=1646464646;
read(m);
for(int i=1;i<=m;++i){
read(px),read(py);
printf("%d\n",solve());
}
fclose(stdin);
fclose(stdout);
return 0;
}
d
【问题描述】
我们有一个序列,现在他里面有三个数1,2,2。我们从第三个数开始考虑:
1、第三个数是2,所以我们在序列后面写2个3,变成1,2,2,3,3。
2、第四个数是3,所以我们在序列后面写3个4,变成1,2,2,3,3,4,4,4。
那么你可以看到,这个序列应该是1,2,2,3,3,4,4,4,5,5,5,6,6,6,6, …。
如果我们设一个数��最后出现的位置为��������(��),那么现在我希望知道
��������(��������(��))等于多少。
【输入格式】
第一行一个整数��,代表数据组数。
接下来��行每行一个整数��。
【输出格式】
��行,每行一个整数,代表��������(��������(��)) mod (109 + 7)的值。
【样例输入】
3
3
10
100000
【样例输出】
11
217
507231491
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于30%的数据,1 ≤ �� ≤ 103。
对于60%的数据,1 ≤ �� ≤ 106。
对于100%的数据,1 ≤ �� ≤ 109
, 1 ≤ �� ≤ 2 × 103。
#include<cstdio>
#include<iostream>
#include<cmath>
#define LL long long
using namespace std;
const LL N = 1400000+7;
const LL mod = 1e9+7;
int n, t;
LL pos[N], sum[N];
struct node{
LL ll, rr;//左右边界位置
}a[N];
int main(){
freopen("d.in", "r", stdin);
freopen("d.out", "w", stdout);
pos[1] = 1, pos[2] = 3; int cnt = 2; LL temp = 2;
a[1].ll = a[1].rr = 1;
a[2].ll = 2; a[2].rr = 3;
for(int i=3; i<=N; i++){
pos[i] = pos[i-1] + cnt;
a[i].rr = pos[i];
a[i].ll = pos[i-1] + 1;
if(i >= pos[temp]){
cnt++; temp++;
}
}
for(int i=1; i<=N; i++){
sum[i] = sum[i-1] + (a[i].rr-a[i].ll+1) * i * (a[i].ll+a[i].rr) / 2 % mod;
sum[i] %= mod;//块内,提出共有的然后用等差算
}
scanf("%d", &t);
LL ans = 0;
for(int i=1; i<=t; i++){
int n; scanf("%d", &n);
int l = 1, r = N;
while(l <= r){//二分在哪一块中
int mid = (l + r) >> 1;
if(a[mid].rr < n) l = mid + 1;
else r = mid - 1;
}
ans = sum[r];
ans += (r+1) * (n-a[r].rr) * (a[r+1].ll+n) / 2 % mod;//剩余的用等差算
printf("%I64d\n", ans % mod);
}
return 0;
}