周测题目解析2

A-POJ - 1661(dp)

在这里插入图片描述
题意
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

J勇士在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当勇士落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当勇士跑到平台的边缘时,开始继续下落。勇士每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算勇士到达地底时可能的最早时间。

Input
第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是勇士开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1…N)。所有坐标的单位都是米。

勇士的大小和平台的厚度均忽略不计。如果勇士恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

Output
对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。

Sample Input
1
3 8 17 20
0 10 8
0 10 13
4 14 3

Sample Output
23

B - 刷子的故事

HDU - 2476
题目描述
有两个长度相等,都只由小写字母构成的字符串A和B. 现在你有一把充满魔♂力的刷子。使用这把刷子,你可以把字符串中连续的一段区间刷♂成一个相同的字符,例如,对于字符串"vandarkholme",把区间[3,6]刷成’d’,可以变成"vanddddholme"。现在你要用这把刷♂子把字符串A变成B,最少要刷多少次?

输入
多组数据,每组数据都有两行:
第一行是字符串A.
第二行是字符串B.
字符串长度不超过100.

输出
在单独的一行中输出结果

样例输入
zzzzzfzzzzz
abcdefedcba
abababababab
cdcdcdcdcdcd

样例输出
6
7

思路

先找出未涂色到B的花费
再找A到B的花费

char a[200];
char b[200];
int dp[200][200];
int dpp[200];
main(void)
{
	while(scanf("%s%s",a+1,b+1)!=EOF)
	{
		int l=strlen(a+1);
		for(int i=1;i<=l;i++)
		for(int j=1;j<=l;j++)
		dp[i][j]=999999999;
		for(int i=1;i<=l;i++)dp[i][i]=1,dpp[i]=99999999;
		for(int len=2;len<=l;len++)
		{
			for(int j=1;j+len<=l+1;j++)
			{
				int i=j+len-1;
				for(int k=j;k<i;k++)
				{
					dp[j][i]=min(dp[j][i],dp[j][k]+dp[k+1][i]);
				}
				if(b[i]==b[j])dp[j][i]--;
			//	debug(dp[j][i]);
			}
		}
		dpp[0]=0;
		for(int i=1;i<=l;i++)
		{
			if(a[i]==b[i])
			{
				dpp[i]=dpp[i-1];
			}
			else
			{
				for(int j=0;j<=i-1;j++)
				{
					dpp[i]=min(dpp[i],dpp[j]+dp[j+1][i]);
				}
			}
			//	debug(dpp[i]);
		}
		printf("%d\n",dpp[l]);
	}
}




C - Lego Building

echo is a curious and clever girl, and she is addicted to the ants recently.

She knows that the ants are divided into many levels depends on ability, also, she finds the number of each level will change.

Now, she will give two kinds of operations as follow :

First, “p a b”, the number of ants in level a change to b.

Second, “q x”, it means if the ant’s ability is rank xth in all ants, what level will it in?

Input

There are multi-cases, and you should use EOF to check whether it is in the end of the input. The first line is an integer n, means the number of level. (1 <= n <= 100000). The second line follows n integers, the ith integer means the number in level i. The third line is an integer k, means the total number of operations. Then following k lines, each line will be “p a b” or “q x”, and 1 <= x <= total ants, 1 <= a <= n, 0 <= b. What’s more, the total number of ants won’t exceed 2000000000 in any time.

Output

Output each query in order, one query each line.

Sample Input

3
1 2 3
3
q 2
p 1 2
q 2
Sample Output

2
1
ZOJ - 3279
一开始用差分和二分做的,但是每次求和n的复杂度太高,正解应该是树状数组维护,log(n)的时间复杂度再加上二分才行

#include<bits/stdc++.h>
using namespace std;
int n,aa,bb,m;
char cmd[2];
int a[500005],c[500005];
int lowbit(int x)//x的二进制表示的从低位到高位连续0的长度 
{
	return x&(-x);
} 
void update(int i,int k)//再i位置加上k 
{
	while(i<=n)
	{
		c[i]+=k;
		i+=lowbit(i);
	}
}
int getsum(int i)//求a[1-i]的和 
{
	int res=0;
	while(i>0)
	{
		res+=c[i];
		i-=lowbit(i);
	}
	return res;
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		memset(c,0,sizeof(c));
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			update(i,a[i]);
		}
		scanf("%d",&m);
		for(int i=1;i<=m;i++)
		{
			scanf("%s",cmd);
			if(cmd[0]=='p')
			{
				scanf("%d%d",&aa,&bb);
				update(aa,bb-a[aa]);
				a[aa]=bb;
			}
			else
			{
				int x;
				scanf("%d",&x);
				int l=1;
				int r=n;
				int mid;
				int ans=99999999;
				while(l<=r)
				{
					mid=(l+r)/2;
					if(x<=getsum(mid))
					{
						ans=min(ans,mid);
						r=mid-1;
					}
					else
					{
						l=mid+1;
					}
				}
				printf("%d\n",ans);
			}
		}
	}
    return 0;
}

D - 自动刷题机

LibreOJ - 2036
DE是两个二分题,特点是寻找一定范围内的最大值最小值、要求最小值最大,最大值最小等。

E - 数列分段 II

LibreOJ - 10014

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值