Codeforces Round #293 (Div. 2) E - Arthur and Questions


只要使a[i], a[i+k], a[i+2k], ……严格递增就可以, 把他们提取出来, 对于连续的一段不确定的数,先贪心最小数是-len/2, 最大数是len-1-len/2,再检查两个端点保证严格递增

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
using namespace std;


#define inf 0x3f3f3f3f
#define eps 1e-9
#define mod 10007
#define FOR(i,s,t) for(int i = s; i < t; ++i )
#define REP(i,s,t) for( int i = s; i <= t; ++i )
#define LL unsigned long long
#define ULL unsigned long long
#define pii pair<int,int>
#define MP make_pair
#define lson id << 1 , l , m
#define rson id << 1 | 1 , m + 1 , r 
#define maxn ( 100000+100 )
#define maxe ( 1000000+10 )
#define mxn 20000

int a[maxn], b[maxn];
char tmp[100];
bool mark[maxn], mb[maxn];

void tonum ( char *s,  int id ) {
	if( s[0] == '?' ) {
		a[id] = 0;
		mark[id] = 1;
		return ;
	}
	int res = 0;
	int len = strlen( s ), st = 0, flag = 0;
	if( s[0] == '-' ) flag = 1, st = 1;
	for( int i = st; i < len; ++i )
		res = res * 10 + s[i] - '0';

	a[id] = flag ? -res : res;
	return ;
}

bool gao ( int len ) {
	int id = -1, last = 0;
	for( int i = 0; i < len; ++i ) if( !mb[i] ) {
		if( id == -1 ) last = b[i], id = i;
		else if( last + i - id > b[i] ) return 0;
	}
	int l = 0, r = 0;
	for( int i = 0; i <= len; ++i ) if( !mb[i] || ( i == len ) ) {
		r = i;
		if( l == r ) {
			l = i + 1;
			continue;
		}
		int cnt = r - l;
		int mi = - cnt / 2;
		int ma = cnt - 1 - cnt /2;
		if( l != 0 && b[l-1] >= mi ) mi = b[l-1] + 1, ma = mi + cnt - 1;
		if( r != len && b[r] <= ma ) ma = b[r] - 1, mi = ma - ( cnt - 1 );
		for( int j = l; j < r; ++j )
			b[j] = mi ++;
		l = i + 1;
	}
	return 1;
}

int main () {

	int n , k;
	while( ~scanf("%d%d", &n, &k ) ) {
		memset( mark, 0, sizeof( mark ) );
		for( int i = 0; i< n; ++i ) {
			scanf("%s", tmp );
			tonum( tmp , i );
		}
		bool flag = 0, ans = 0, temp = 0;
		for( int i = 0; i < k && !flag; i++) {
			int len = 0, j = i;
			while( j < n ) b[len] = a[j], mb[len++] = mark[j], j += k;
			if( gao ( len ) ) {
				j = i; 
				len = 0;
				while( j < n ) a[j] = b[len++], j += k;
			}
			else flag = 1;
		}
		if( flag ) puts("Incorrect sequence");
		else {
			for( int i = 0; i < n; ++i )
				printf("%d%c", a[i], i == n-1 ? '\n' : ' ' );
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值