[机房练习赛7.7]haokunnan

T1:

Description

Let's play the game Zuma!

There are a sequence of beads on a track at the right beginning. All the beads are colored but no three adjacent ones are allowed to be with a same color. You can then insert beads one by one into the sequence. Once three (or more) beads with a same color become adjacent due to an insertion, they will vanish immediately.

Note that it is possible for such a case to happen for more than once for a single insertion. You can't insert the next bead until all the eliminations have been done.

Input

Given both the initial sequence and the insertion series, you are now asked by the fans to provide a playback tool for replaying their games. In other words, the sequence of beads after all possible eliminations as a result of each insertion should be calculated.

The first line gives the initial bead sequence. Namely, it is a string of capital letters from 'A' to 'Z', where different letters correspond to beads with different colors.

The second line just consists of a single interger n, i.e., the number of insertions.

The following n lines tell all the insertions in turn. Each contains an integer k and a capital letter Σ, giving the rank and the color of the next bead to be inserted respectively. Specifically, k ranges from 0 to m when there are currently m beads on the track.

Output

n lines of capital letters, i.e., the evolutionary history of the bead sequence.

Specially, "-" stands for an empty sequence.

Example

Input

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

Output

ABCCBA
AABCCBA
AABBCCBA
-
A
Restrictions

0 <= n <= 10^4

0 <= length of the initial sequence <= 10^4

Time: 2 sec

Memory: 256 MB

Hints

List

描述

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

开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。

游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。

输入

第一行是一个由大写字母'A'~'Z'组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。

第二行是一个数字n,表示整个回放过程共有n次操作。

接下来的n行依次对应于各次操作。每次操作由一个数字k和一个大写字母Σ描述,以空格分隔。其中,Σ为新珠子的颜色。若插入前共有m颗珠子,则k ∈ [0, m]表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。

输出

输出共n行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上的珠子序列。

样例

如果轨道上已没有珠子,则以“-”表示。

见英文题面

限制

0 ≤ n ≤ 10^4

0 ≤ 初始珠子数量 ≤ 10^4

时间:2 sec

内存:256 MB


一道模拟游戏的题,正解是双向链表,但strcpy也能过(数据有点坑)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char s[20005],s2[20005],ch;
int len=0,n,k;
bool check( int x ){
	int l = x, r = x;
	while( l && s[l-1] == s[x] ) l--;
	while( r < len && s[r] == s[x] ) r++;
	if( r - l > 2 ){
		strcpy(s2,s+r); strcpy(s+l,s2);
		len -= r-l; k = l;
		return true;
	}
	return false;
}
int main(){
	freopen("hao.in","r",stdin);
	freopen("hao.out","w",stdout);
	gets(s); len = strlen(s);
	scanf("%d",&n);
	for( int i = 1; i <= n; i++ ){
		scanf("%d %c", &k, &ch);
		strcpy(s2,s+k);
		s[k] = ch; len++;
		strcpy(s+k+1,s2);
		while(len){ if(!check(k)) break; }
		if(!len) puts("-"); 
		else printf("%s\n",s);
	}
	return 0;
}
T2:

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
【样例解释】
【数据规模与约定】
对于 的数据,n<=1000000 。

RMQ水过,但是太慢了

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 2000000 + 5;
int st[N][25],n,a[N],sta[N],top;
int find( int x, int y ){
	int p=0; if( x == y ) return x;
	while( x+(1<<p) <= y-(1<<p) ) p++;
	return max(st[x][p],st[y-(1<<p)][p]);
}
int main(){
	freopen("kun.in","r",stdin);
	freopen("kun.out","w",stdout);
	scanf("%d", &n);
	for( int i = 1; i <= n; i++ ) scanf("%d", &a[i]);
	for( int i = 1; i <= n; i++ ) st[i][0] = a[i];
	for( int j = 1; j <= 20; j++ )
		for( int i = 1; i <= n; i++ )
			st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
	for( int i = 1; i <= n; i++ ){
		sta[++top] = a[i];
		int maxhou = find(i+1,n+1); if( i == n ) maxhou = a[n];
		while( sta[top] >= maxhou && top > 0 ) printf("%d ", sta[top]),top--;
	}
	while( top ) printf("%d ", sta[top]),top--;
	return 0;
}

T3:

【问题描述】
我们 有一个序列 ,现在他里面有三个数 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,…。
如果我们设一个数 如果我们设一个数 如果我们设一个数 如果我们设一个数 如果我们设一个数 如果我们设一个数 如果我们设一个数 如果我们设一个数x最后出现的位置为last(x),那么现在我希望知道last(last(x))等于多少 。
【输入格式】
第一行 一个整数T,代表数据组数。
接下来T行每行一个整数x。
【输出格式】
T行,每行一个整数 ,代表last(last(x)) mod (109+7)的值 。
【样例输入】
3
3
10
100000
【样例输出】
11
217
507231491
【数据规模与约定】
对于 30%的数据, 1≤N≤10³。
对于 60%的数据 ,1≤N≤106。
对于 100%的数据 ,1≤N≤109,1≤T≤2×10³。


先暗中观察小数据

          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

好吧,看不出来

把a写出来 1 2 2 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 9 10 10 10 10 10

我们可以分段,将连续是i个的归为一段

1 | 2 2 3 3 | 4 4 4 5 5 5 | 6 6 6 6 7 7 7 7 8 8 8 8 | 9 9 9 9 9 10 10 10 10 10 11 11 11 11 11 |

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

你发现了什么,就是a[i]*i啊

先预处理,将a[i]相同的一块的左端和右端保存起来,再等差序列求和就可以了

至于last(last(x)) - last(last(x-1)) 为什么是那么多,其实设k=last(i),k1=last(i-1) last(k)-last(k1)的关系相当于a数组中的对应关系,然后就没什么了

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const ll N = 1400000;
const ll mod = 1000000000+7;
int n,t;
ll last[N],k[N],now=2;
struct node{ ll lf,rg; }a[N];
int main(){
    freopen("nan.in","r",stdin);
    freopen("nan.out","w",stdout);
    last[1] = 1, last[2] = 3; int q = 2;
    a[1].lf = a[1].rg = 1;
    a[2].lf = 2; a[2].rg = 3;
    for( int i = 3; i <= 1400000; i++ ){
        last[i] = last[i-1]+q;
        a[i].rg = last[i]; a[i].lf = last[i-1]+1;
        if( i >= last[now] ){ q++; now++; }
    }
    for( int i = 1; i <= 1400000; i++ ){
        k[i] = ( k[i-1] + (a[i].rg-a[i].lf+1)*(a[i].lf+a[i].rg)*i/2%mod )%mod;
    }
    scanf("%d",&t);
    ll ans=0;
    for( int i = 1; i <= t; i++ ){
        int n; scanf("%d",&n);
        int l = 1, r = 1400000;
        while( l <= r ){
            int mid = (l+r)>>1;
            if( a[mid].rg < n ) l = mid+1;
            else r = mid-1;
        }
        ans = k[r];
        (ans += (r+1)*(n-a[r].rg)*(a[r+1].lf+n)/2%mod)%=mod;
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值