10.29 NOIP模拟赛(afternoon)

有想要数据的可以私我哦 评论一下就可以

这里写图片描述

【问题描述】

祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。

这里写图片描述

开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。

【输入格式】

第一行是一个由大写字母'A'~'Z'组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。
第二行是一个数字 ,表示整个回放过程共有 次操作。
接下来的 行依次对应于各次操作。每次操作由一个数字 和一个大写字母 描述,以空格分隔。其中, 为新珠子的颜色。若插入前共有 颗珠子,则 表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。

【输出格式】

输出共n行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上的珠子序列。
如果轨道上已没有珠子,则以“-”表示。

【样例输入】

ACCBA
5
1 B
0 A
2 B
4 C
0 A

【样例输出】

ABCCBA
AABCCBA
AABBCCBA
A

【样例解释】

你以为山里又有座庙?

【数据规模与约定】

 100%的数据满足1<=n<=10^3,1<=m<=2*10^3。

思路:

一道恶心的模拟题,注意数据可能开始就有连着的三个球....

代码

#include <cstdio>  
#include <cstring>  

const int SZ = 1<<20;  //快速io  

char ch[20001];  
char temp[20001];  
int size=0,pos;  


int res(int a)  
{  
    int head = a,last = a;  
    char elem;  

    elem = ch[a];  
    while(ch[head] == elem && head) head--;  
    if(head || ch[head] != elem) head++;  
    while(ch[last] == elem && last < size) last++;  
    if(last - head > 2)  
    {  
        strcpy(temp,ch + last);  
        strcpy(ch + head, temp);  
        size = size + head - last;  
        pos = head;  
        return 1;  
    }  
    else  
    return 0;  
}  
int main()  
{  
    int i = 0;  
    int n;  
    char e;  

    gets(ch);  
    while(ch[size] >= 'A' && ch[size] <= 'Z')size++;  
    scanf("%d", &n);  
    while(n--)  
    {  
        scanf("%d %c",&pos,&e);  
        strcpy(temp, ch + pos);  
        strcpy(ch + pos + 1, temp);  
        ch[pos] = e;size++;  
        while(res(pos) && size);  
        if(size)  
        puts(ch);  
        else  
        puts("-");  
    }  
    return 0;  
}  

//莫名80
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 2000;
const int maxm = 160010;

int len;
char str[maxm * maxn];
struct Node {
    char type;
    Node *next, *last;
    Node (char c) {
        type = c;
        next = last = NULL;
    }
}*head, *tail;

int main() {
    freopen("ha.in","r",stdin);
    freopen("ha.out","w",stdout);

    head = tail = NULL;
    int n;
    char c;
    while (1) {
        scanf("%c", &c);
        if (c == '\n') break;
        Node *n = new Node(c);
        n -> last = tail;
        if (tail) tail -> next = n;
        tail = n;
        if (!head) head = n;
    }
    len = 0;
    scanf("%d", &n);
    while (n--) {
        int pos;
        char t[3];
        scanf("%d %s", &pos, t);
        Node *now = head;
        for (int i = 0; i < pos; ++ i)
            now = now -> next;
        //insert
        Node *newnode = new Node(t[0]);
        if (!head && !tail) {
            head = tail = newnode;
        } else {
            newnode -> next = now;
            if (now) {
                newnode -> last = now -> last;
                if (now -> last) now -> last -> next = newnode;
                else head = newnode;
                now -> last = newnode;
            }
            else {
                tail -> next = newnode;
                newnode -> last = tail;
                tail = newnode;
            }
        }
        //modify
        while (1) {
            while (newnode -> next && newnode -> type == newnode -> next -> type) newnode = newnode -> next;
            int cnt = 1;
            while (newnode -> last && newnode -> type == newnode -> last -> type)
                cnt ++, newnode = newnode -> last;
            if (cnt > 2) {
                while (cnt --) {
                    if (newnode -> last) newnode -> last -> next = newnode -> next;
                    if (newnode -> next) newnode -> next -> last = newnode -> last;
                    Node *tmp = newnode;
                    if (head == newnode) head = head -> next;
                    if (newnode -> next) newnode = newnode -> next;
                    else {
                        newnode = newnode -> last;
                        tail = newnode;
                    }
                    delete tmp;
                }
            } else break;
            if (!newnode) {
                head = tail = NULL;
                break;
            }
        }
        if (!head) str[len++] = '-', str[len++] = '\n';
            //puts("-");
        else {
            for (Node *p = head; p; p = p -> next)
                str[len++] = p -> type;
                //printf("%c", p->type);
            str[len++] = '\n';
            //puts("");
        }
    }
    printf("%s", str);
    return 0;
}
//80
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 4010
using namespace std;
char a[N];
int n,m;
int main(){
    gets(a+1);
    n=strlen(a+1);
    scanf("%d",&m);
    while(m--){
        int pos,l,r;char s[10];
        scanf("%d%s",&pos,s);
        for(int i=n+1;i>=pos+2;i--) a[i]=a[i-1];
        n++;
        a[pos+1]=s[0];
        while(true){
            for(l=pos;(l>=1)&&(a[l]==a[pos+1]);l--) continue;
            for(r=pos+2;(r<=n)&&(a[r]==a[pos+1]);r++) continue;
            int len=r-l-1;
            if(len>=3){
                pos=l;n-=len;
                for(int i=pos+1;i<=n;i++) a[i]=a[i+len];
                for(int i=n+1;i<=n+len;i++) a[i]=0;
                a[n+1]=0;
            }
            else break;
        }
        if(n==0) printf("-\n");
        else printf("%s\n",a+1);
    }
    return 0;
}

这里写图片描述

【问题描述】

栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借助一个栈,依次将数组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行。
第一行包含一个整数n,表示入栈序列长度。
第二行包含n个整数,表示入栈序列。输入数据保证给定的序列是1到n的全排列,即不会出现重复数字。

【输出格式】

仅一行,共n个整数,表示你计算出的出栈序列。

【样例输入】

3
2 1 3

【样例输出】

3 1 2

【样例解释】

这回山里有座塔。

【数据规模与约定】

对于30%的数据1<=n<=10^3。
对于60%的数据1<=n<=10^5。
对于100%的数1<=n<=10^6。

思路

可以用stl,要让字典序尽量大,所以最先输出的数尽量大

代码

#include<stack>
#include<cstdio>
#include<iostream>
#define MAXN 1000010
using namespace std;
stack<int> s;
int n;
int m[MAXN],a[MAXN];
inline void read(int&x) {
    int f=1;x=0;char c=getchar();
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=10*x+c-48,c=getchar();
    x=x*f;
}
int main() {
    freopen("haha.in","r",stdin);
    freopen("haha.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=n;i>=1;i--) m[i]=max(a[i],m[i+1]);
    s.push(a[1]);
    for(int i=2;i<=n;i++) {
        while((!s.empty())&&(s.top()>m[i])) 
          printf("%d ",s.top()),s.pop();
        s.push(a[i]);
    }
    while(!s.empty()) printf("%d ",s.top()),s.pop();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

这里写图片描述

【问题描述】

小Q对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,小Q会在x轴正半轴和y轴正半轴分别挑选n个点。随后,他将x轴的点与y轴的点一一连接,形成n条线段,并保证任意两条线段不相交。小Q确定这种连接方式有且仅有一种。最后,小Q会给出m个询问。对于每个询问,将会给定一个点P(px,py),请回答线段OP与n条线段会产生多少个交点?
小Q找到了正在钻研数据结构的你,希望你可以帮他解决这道难题。

【输入格式】

第1行包含一个正整数 ,表示线段的数量;
第2行包含 个正整数,表示小Q在x轴选取的点的横坐标;
第3行包含 个正整数,表示小Q在y轴选取的点的纵坐标;
第4行包含一个正整数 ,表示询问数量;
随后m行,每行包含两个正整数 ,表示询问中给定的点的横、纵坐标。

【输出格式】

共m行,每行包含一个非负整数,表示你对这条询问给出的答案。

【样例输入】

3
4 5 3
3 5 4
2
1 1
3 3

【样例输出】

0
3

【样例解释】

然后塔里啥都没有。

【数据规模与约定】

对于50%的数据1<=n,m<=2*10^3,。
对于100%的数据1<=n,m<=2*10^5
坐标范围<=10^8;

思路

我们可以发现想 x,y 轴的点要想不相交
那就要把坐标小的点相连,那么可以先把 x,y 轴的点排序
在相连就可以了
如果p点和第i条直线相交,那么和它前i条线一定相交
那么我们可以二分来找最多和多少直线相交就可以了

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1e9
#define maxn 200010
using namespace std;
int n,m,a[maxn],b[maxn];
struct node{
    int x,y;
}p[maxn];
inline void read(int&x){
    x=0;int f=1;char c=getchar();
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    x=x*f;
}
inline bool Judge(int i,int x,int y){
    double Y=(double)p[i].y-(double)x*(double)p[i].y/(double)p[i].x;
    return Y<=y;
}
int main() {
    freopen("hahaha.in","r",stdin);
    freopen("hahaha.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    for(int i=1;i<=n;i++) read(b[i]);
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    for(int i=1;i<=n;i++) p[i].x=a[i],p[i].y=b[i];
    n++;
    p[n].x=inf;
    p[n].y=inf;
    read(m);
    int x,y;
    while(m--){
        read(x);read(y);
        int l=0,r=n,pos=0;
        while(l<=r){
            int mid=l+r>>1;
            if(Judge(mid,x,y)){
                l=mid+1;pos=max(pos,mid);
            }
            else r=mid-1;
        }
        printf("%d\n",pos);
    }
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值