Codeforces 508E Arthur and Brackets

题意:

给出括号序列中每个右括号可能离对应左括号多远  求这个括号序列

思路:

记忆化搜索解决  用f[l][r]表示对于第l个左括号到第r个左括号区间最前面的左括号与其对应右括号的距离

状态只有n^2个  不用担心TLE

求f[l][r]的方法为  如果最前的左括号可以包住l+1~r个括号就尝试包起来  否则将l~r分治为l~x和x+1~r两个子问题

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef unsigned long long ULL;
#define N 610

int n;
int l[N],r[N];
int f[N][N];

bool dfs(int s,int t){
	//printf("%d %d %d\n",s,t,f[s][t]);
	if(f[s][t]<0) return false;
	if(f[s][t]>0) return true;
	if(s==t){
		if(l[s]==1){
			f[s][t]=1;
			return true;
		}
		f[s][t]=-1;
		return false;
	}
	int len=(t-s)*2+1;
	if(l[s]<=len&&len<=r[s]){
		if(dfs(s+1,t)){
			f[s][t]=len;
			return true;
		}
	}
	for(int i=(l[s]&1)?l[s]:l[s]+1;i<=r[s]&&i<=len;i+=2){
		if(s+i/2<t&&dfs(s,s+i/2)&&dfs(s+i/2+1,t)){
			f[s][t]=i;
			return true;
		}
	}
	f[s][t]=-1;
	return false;
}

void print(int s,int t){
	if(s>t) return;
	//printf("%d %d %d\n",s,t,f[s][t]);
	if(f[s][t]==(t-s)*2+1){
		putchar('(');
		print(s+1,t);
		putchar(')');
		return;
	}
	putchar('(');
	print(s+1,s+f[s][t]/2);
	putchar(')');
	print(s+f[s][t]/2+1,t);
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);
	if(dfs(1,n)) print(1,n),puts("");
	else puts("IMPOSSIBLE");
	return 0;
}
时间: 2024-08-03 16:32:45

Codeforces 508E Arthur and Brackets的相关文章

codeforces 508 E. Arthur and Brackets

题目链接: http://codeforces.ru/problemset/problem/508/E 题意: 有n对括号,按顺序,给出每对括号长度的范围,输出一种情况. 限制: 1 <= n <= 600 思路: 贪心:能匹配的先匹配. 括号匹配问题,果断先思考用栈能不能做. C++ Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3

CodeForces - 552E Vanya and Brackets

Vanya and Brackets Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Description Vanya is doing his maths homework. He has an expression of form , where x1, x2, ..., xn are digits from 1 to 9, and sign represents either a p

Codeforces 552E Vanya and Brackets(贪心 + 表达式计算)

题目链接 Vanya and Brackets 题目大意是给出一个只由1-9的数.乘号和加号组成的表达式,若要在这个表达式中加上一对括号,求加上括号的表达式的最大值. 我们发现,左括号的位置肯定是最左端或者某个乘号右边,右括号的位置肯定是最右段或者某个乘号左边. 而乘号最多只有15个,那么暴力枚举就可以了. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b);

CodeForces 380C Sereja and Brackets(扫描线+树状数组)

[题目链接] http://codeforces.com/problemset/problem/380/C [题目大意] 给出一个括号序列,求区间内左右括号匹配的个数. [题解] 我们发现对于每个右括号,其匹配的左括号是固定的, 我们保存每个右括号匹配的左括号位置, 对区间询问进行线扫描,将扫描的区间右端点及其之前所有的右括号对应的左括号位置做标记, 只要查询询问区间的标记个数就是答案,这个可以用树状数组维护. [代码] #include <cstdio> #include <algor

CodeForces 525D Arthur and Walls

广搜.看了官方题解才会的..... 定义2*2的小矩阵,有三个是点,一个是星,这样的小矩阵被称为元素块. 首先把所有元素块压入队列,每次取出对头,检查是否还是元素块,如果是 那么将那个*改为点,否则跳过 改完之后,检查周围8个点是否是元素块,如果有新产生的元素块,那么压入队列. 这样操作完之后就是答案. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include&l

Codeforces 380C. Sereja and Brackets【线段树】

题目大意: 给出一串括号,有m个查询(包含a,b)问区间[a,b]之间有多少个匹配的括号 做法: 处理两个数组r[i](代表从1到i之间有多少个已匹配的右括号),l[i](代表从1到i之间有多少个没有匹配的左括号).我们要算[a,b]之间的匹配的括号数,首先用r[b]-r[a-1],但是遮掩更有可能a到b之间的右括号是在[1,a-1]之间被匹配的,那么再减去l[a-1],但是减去的这一部分中,也有可能是在[b+1,len]这个区间中被匹配,要加上这一部分不该减去的数值,那么只需要在加上min(l

Codeforces 557C Arthur and Table 砍桌腿

题意:有n个桌腿,要砍掉某些桌腿使得剩下的桌腿能支撑桌子.规定剩下的桌腿中长度最大的桌腿的数量如果超过一半即可支撑桌子.砍掉每个桌腿需要付出代价.求最小的代价和. 枚举.假如最后剩下的桌腿的最大长度为lenth,这样长度的桌腿有num个.那么长度大于lenth的桌腿肯定都被砍去了,然后在剩下的桌腿中按照代价从大到小选择num - 1个桌腿留下来(不砍),将剩余的再砍去,这样一定是最小的代价和.当然也不是无脑枚举,能枚举是因为代价种类很少,才200个.首先我们按桌腿的长度排序,然后枚举每种长度作为

Arthur and Brackets

n<605设计出n对夸号  给出n个条件每个条件为[l,r] 表示第i对夸号右夸号离左夸号的距离,然后夸号的右夸号出现的顺序必须按照给的顺序 出现, 那么如果存在就输出否则输出impossilbe , 我们知道如果一个夸号在 L位置,那么 另一个夸号就在 L+cnt 这个位置, 那么我们就可以知道在L=1 和L+cnt-1 这之间的夸号只要合法就可以了 #include <iostream> #include <cstdio> #include<algorithm>

codeforces D - Arthur and Walls

这题说的是给了一个矩阵,必须让.连接起来的图形变成矩形,2000*2000的矩形,那么我们就可以知道了,只要是存在一个有点的区域应该尽量将他削为矩形,那么将这个图形进行缩放,最后我们知道只要存在一个2*2 的矩形中有1个是*就必须将这个*号去掉. 采用bfs去做 1 #include <iostream> 2 #include <algorithm> 3 #include <string.h> 4 #include <cstdio> 5 #include &