2017.9.4 模拟考试

45 篇文章 0 订阅
33 篇文章 0 订阅

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值