2019.01.21【NOIP提高组】模拟 B 组

76 篇文章 0 订阅
41 篇文章 0 订阅

JZOJ 4208 线段树什么的最讨厌了

题目

询问多段区间,是否存在一个 [ 0 ∼ n ] [0\sim n] [0n]的线段树为该区间


分析

那么区间 [ l ∼ r ] [l\sim r] [lr]可以扩展成 [ l ∼ r + t ] , [ l − t ∼ r ] , [ l − t − 1 ∼ r ] , [ l ∼ r + t − 1 ] ( t = r − l + 1 ) [l\sim r+t],[l-t\sim r],[l-t-1\sim r],[l\sim r+t-1](t=r-l+1) [lr+t],[ltr],[lt1r],[lr+t1](t=rl+1)这样逆流而上,遇到 l = 0 l=0 l=0的时候 r r r即为答案


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef unsigned ust;
ust lim,ans;
inline ust iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void dfs(ust l,ust r){
	if (r>lim||r>ans||l>r) return;
	if (!l) {ans=r; return;}
	rr ust t=r-l+1;
	if (r+t<=lim&&l>=(t<<1)) dfs(l,r+t);
	if (l>=t) dfs(l-t,r);
	if (r+t<lim&&l>=(t<<1)-1) dfs(l,r+t-1);
	if (l==t+1||l>=t*3+2) dfs(l-t-1,r);
}
signed main(){
	for (rr ust t=iut();t;--t){
		rr ust l=iut(),r=iut(); lim=iut();
		if (l==r||!l) printf("%u\n",r);
		else if (r>lim) printf("-1\n");
		else{
			ans=2e9; dfs(l,r);
			if (ans==2e9) printf("-1\n");
			    else printf("%u\n",ans);
		}
	}
	return 0;
}

JZOJ 4209 【五校联考1day1】已经没有什么好害怕的了

题目

给定一个长度为n 只包含左括号和右括号的序列,问经过每一个位置的合法子串有多少个。如果A 和B 都是合法的串,那么(A) 和AB 都是合法的串。


分析

首先对于整个子串的增加个数可以用差分实现,然后用栈维护找到同级且相连的括号,用类似于双向链表的方式连接起来,然后对于每一个前驱和后继必须和括号有关,所以说用这样的方式求出答案


代码

#include <cstdio>
#include <cstring>
#include <stack>
#define rr register
using namespace std;
const int N=1000010,mod=1000000007;
int l[N+1],r[N+1],L[N+1],R[N+1];
signed main(){
	rr int t; scanf("%d",&t);
	while (t--){
		rr char c=getchar(); rr int len=0;
		rr stack<int>zh; rr long long ans=0,f=0;
		while (c!='('&&c!=')') c=getchar();
		while (c=='('||c==')'){
			++len; if (c=='(') zh.push(len);
			else if (zh.size()) l[r[zh.top()]=len+1]=zh.top(),zh.pop();
			c=getchar();
		}
		for (rr int i=len+1;i;--i) R[l[i]]+=++R[i];
		for (rr int i=1;i<=len;++i) L[r[i]]+=--L[i];
		for (rr int i=1;i<=len;++i) ans+=(f+=L[i]+R[i])*i%mod;
		memset(l,0,sizeof(l)); memset(r,0,sizeof(r));
		memset(L,0,sizeof(L)); memset(R,0,sizeof(R));
		printf("%lld\n",ans);
	}
	return 0;
}

JZOJ 4210 【五校联考1day1】我才不是萝莉控呢

题目

有一个长度为 n n n的正整数数组 A A A,满足 A i ≥ A i + 1 A_i\geq A_{i+1} AiAi+1,现在构造一个数组 B B B,令 B i = ∑ j = i n A j B_i=\sum_{j=i}^nA_j Bi=j=inAj
现在,有一个 n × n n\times n n×n的网格图,左下角坐标是 ( 1 , 1 ) (1, 1) (1,1),右上角坐标是 ( n , n ) (n, n) (n,n)。每一时刻,如果他现在在 ( x , y ) (x, y) (x,y),他可以选择走到 ( x − 1 , y + 1 ) (x-1,y+1) (x1,y+1)或者 ( x , y + 1 2 ) (x, \frac{y+1}{2}) (x,2y+1),如果选择后者,他要支付 B x B_x Bx的代价。
现在他想从 ( n , 1 ) (n,1) (n,1)走到(1, 1),支付的代价最少是多少吗?注意在任何时候他都不能离开这个网格图。


分析

根据dalao的解释,如果倒过来推,只能向上或者掉下来,这长得很像哈夫曼树的合并,所以说合并果子原题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值