2017.7.7 机房测试 (模拟,贪心,二分)

来源:互联网 发布:iphone怎么快速开数据 编辑:程序博客网 时间:2024/04/29 12:41

hao

【问题描述】

祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。
开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。
这里写图片描述
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。

【输入格式】

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

【输出格式】

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

【样例输入】

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

【样例输出】

ABCCBA
AABCCBAA
ABBCCBA
-
A

【数据规模与约定】

的数据满足
1<=n<=1000
1<=m<=2000

【解题报告】

想不到第一道模拟题大部分人都没有过。。。。
因为它是一道恶心的模拟。
注意即使一开始出现了相邻的多余3个的球,也只有被同色碰撞才会消失。
一开始可能没有球(所以用gets)。
还有这个插入的写法简直就是黑魔法啊。。。
本着便于理解的原则,请点击http://www.2144.cn/flash/13326.htm

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 20005char ch[N],temp[N],e;  int n,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()  {       freopen("hao.in","r",stdin);    freopen("hao.out","w",stdout);    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; }  

kun

【问题描述】

栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借助一个栈,依次将数组1,3,2按顺序入栈或出栈,可对其从大到小排序: 1入栈;3入栈;3出栈;2入栈;2出栈;1出栈。 在上面这个例子中,出栈序列是3,2,1,因此实现了对数组的排序。 遗憾的是,有些时候,仅仅借助一个栈,不能实现对数组的完全排序。例如给定数组2,1,3,借助一个栈,能获得的字典序最大的出栈序列是3,1,2: 2入栈;1入栈;3入栈;3出栈;1出栈;2出栈。 请你借助一个栈,对一个给定的数组按照出栈顺序进行从大到小排序。当无法完全排序时,请输出字典序最大的出栈序列。

【输入格式】

输入共 行。
第一行包含一个整数 ,表示入栈序列长度。
第二行包含 个整数,表示入栈序列。输入数据保证给定的序列是 到n的全排列,即不会出现重复数字。

【输出格式】

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

【样例输入】

3
2 1 3

【样例输出】

3 1 2

【数据规模与约定】

对于30% 的数据,1<=n<=1000。
对于 60%的数据, 1<=n<=100000。
对于 100%的数据, 1<=n<=1000000。

【解题报告】

要让字典序尽量大,所以最先输出的数尽量大。
然后乱搞就可以了。

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 1000005int n, a[N], stack[N],top=0,nowmax;bool vis[N];int main() {    freopen("kun.in","r",stdin);    freopen("kun.out","w",stdout);    memset(vis,0,sizeof(vis));    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%d",&a[i]);    nowmax=n;    for(int i=1;i<=n;i++)     {        stack[++top]=a[i];        vis[a[i]]=true;        if(nowmax==a[i])         {            top--;            printf("%d ",a[i]);            while(vis[nowmax]) nowmax--;        }        while(a[i+1]<stack[top]&&stack[top]>nowmax)         {            printf("%d ",stack[top]);            top--;        }    }    return 0;}

nan

【问题描述】

我们有一个序列,现在他里面有三个数 。我们从第三个数开始考虑:
1、第三个数是 ,所以我们在序列后面写 个 ,变成 。
2、第四个数是 ,所以我们在序列后面写 个 ,变成 。
那么你可以看到,这个序列应该是 。
如果我们设一个数 最后出现的位置为 ,那么现在我希望知道 等于多少。

【输入格式】

第一行一个整数 ,代表数据组数。
接下来 行每行一个整数 。

【输出格式】

行,每行一个整数,代表 的值。

【样例输入】

3
3
10
100000

【样例输出】

11
217
507231491

【数据规模与约定】

对于 的数据,1<=x<=1000 。
对于 的数据,1<=x<=1000000 。
对于 的数据, 1<=x<=1e9,1<=T<=2000。

【解题报告】

60%是这么做的:
首先打表找出last和last(last) (这里只写10组):
x ——————1 2 3 4 5 6 7 8 9 10

a[x] —————1 2 2 3 3 4 4 4 5 5

last(x)————1 3 5 8 11 15 19 23 28 33

last(last(x)) ——1 5 11 23 38 62 90 122 167 217

算last(last(x))-last(last(x-1)):

last(last(x))-last(last(x-1)) 1  4  6  12  15  24  28  32  45  50

又可以写成: 1*1 2*2 2*3 3*4 3*5 4*6 4*7 4*8 4*9 5*10

可以看出,后面的数1~10就等于i,而前面的数刚好就是a[x]
于是预处理的时候就将各个分块(a[x]相同的为一块)的left和right保存起来,这样依次用等差序列求和公式就能得出ans了
至于n在中间的情况(如last(last(7)),就用a[4]的right和n(7)做比较,n小则只加上left到n的等差序列,这样就可以过60%的数据

至于100%的数据,要用到前缀和和二分的方法:前缀和求前面连续分块的和,二分求出离n最近的a[rightn].right的编号rightn,
再加上后面的等差序列(同上),可以算出大约第130万个分块的长度超过了1e9,所以二分是可行的。

代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define N 1400007#define mod 1000000007long long n,t;long long last[N];long long llst[N];long long k[N];struct node{    long long left,right;}a[N];long long temp=2;int main(){    freopen("nan.in","r",stdin);    freopen("nan.out","w",stdout);    last[1]=1,last[2]=3;    long long q=2;    a[1].left=a[1].right=1;    a[2].left=2;a[2].right=3;    for(long long i=3;i<=1400000;i++)    {        last[i]=last[i-1]+q;        a[i].right=last[i];        a[i].left=last[i-1]+1;        if(i>=last[temp])        {            q++;temp++;        }    }    for(long long i=1;i<=1400000;i++)    {        k[i]=k[i-1]+(a[i].right-a[i].left+1)*i*(a[i].left+a[i].right)/2%mod;        k[i]%=mod;    }    long long ans=0;    for(scanf("%I64d",&t);t;--t)    {        long long n;scanf("%I64d",&n);        long long l=1,r=1400000;        while(l<=r)        {            long long mid=(l+r)>>1;            if(a[mid].right<n)l=mid+1;            else r=mid-1;        }        ans=k[r];        ans+=(r+1)*(n-a[r].right)*(a[r+1].left+n)/2%mod;        printf("%I64d\n",ans%mod);    }    return 0;}
原创粉丝点击