2017.10.3北京清北综合强化班DAY3
括号序列(bracket)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK有一个括号序列,但这个序列不一定合法。
一个合法的括号序列如下:
()是合法的括号序列。
若A是合法的括号序列,则(A)是合法的括号序列。
若A和B分别是合法的括号序列,则AB是合法的括号序列。
LYK想通过尽可能少的操作将这个不一定合法的括号序列变成合法的括号序列。一次修改操作是将某个字符变成另一个字符。
你能帮帮它吗?
输入格式(bracket.in)
一行一个字符串S。
输出格式(bracket.out)
一个数表示最少修改次数。
输入样例
()))
输出样例
1
样例解释
将第二个字符修改成(即可。
数据范围
对于30%的数据|S|<=10。
对于60%的数据|S|<=1000。
对于100%的数据|S|<=100000。且|S|是偶数。
题解:贪心
遇到右括号,如果之前有左括号就抵消 否则 step++,把它变成左括号
最后剩下一堆左括号,之前step+左括号个数/2 即可。
本萌妹的AC代码真好看..
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; string s;
int len,top,ans; int main(){
freopen("bracket.in","r",stdin);
freopen("bracket.out","w",stdout);
cin>>s;len=s.length();
for(int i=;i<len;i++){
if(s[i]=='(')top++;
if(s[i]==')'){
if(top)top--;
else ans++,top++;
}
}
printf("%d\n",ans+top/);
fclose(stdin);fclose(stdout);
return ;
}
AC
公交车(bus)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK在玩一个游戏。
有k群小怪兽想乘坐公交车。第i群小怪兽想从xi出发乘坐公交车到yi。但公交车的容量只有M,而且这辆公交车只会从1号点行驶到n号点。
LYK想让小怪兽们尽可能的到达自己想去的地方。它想知道最多能满足多少小怪兽的要求。
当然一群小怪兽没必要一起上下车,它们是可以被分开来的。
输入格式(bus.in)
第一行三个数k,n,M。
接下来k行每行3个数xi,yi和ci。其中ci表示第i群小怪兽的小怪兽数量。
输出格式(bus.out)
一个数表示最多有多少只小怪兽能满足要求。
输入样例
3 5 3
1 3 4
3 5 2
1 5 3
输出样例
5
样例解释
第一群的3只小怪兽在1号点上车,并在3号点下车。
第二群的2只小怪兽在3号点上车,5号点下车。
数据范围
对于30%的数据小怪兽的总数不超过10只,n<=10。
对于另外30%的数据k,n<=1000。
对于100%的数据1<=n<=20000,1<=k<=50000,1<=M<=100,1<=ci<=100,1<=xi<yi<=n。
题解:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring> using namespace std; int k,n,m,ans;
int c[];
struct GS{
int x,y,c;
}gs[]; bool cmp(GS a,GS b){
return a.y-a.x<b.y-b.x;
} void dfs(int x,int sum){
if(x==k+){
ans=max(ans,sum);
return;
}
int maxx=-;
for(int i=gs[x].x;i<gs[x].y;i++)maxx=max(maxx,c[i]);
int gg=min(gs[x].c,m-maxx);
for(int i=gs[x].x;i<gs[x].y;i++)c[i]+=gg;
dfs(x+,sum+gg);
for(int i=gs[x].x;i<gs[x].y;i++)c[i]-=gg;
dfs(x+,sum);
} int main(){
freopen("bus.in","r",stdin);
freopen("bus.out","w",stdout);
scanf("%d%d%d",&k,&n,&m);
//k群小怪兽,n个站,容量m
for(int i=;i<=k;i++)
scanf("%d%d%d",&gs[i].x,&gs[i].y,&gs[i].c);
if(k<=){
dfs(,);
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
sort(gs+,gs+k+,cmp);
for(int i=;i<=k;i++){
int l=gs[i].x,r=gs[i].y;
int maxx=-;
for(int h=l;h<r;h++)maxx=max(maxx,c[i]);
int gg=min(gs[i].c,m-maxx);
ans+=gg;
for(int h=l;h<r;h++)c[i]+=gg;
}
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
玄学贪心20
首先看这么一个经典问题,寻找尽量多的互不相交的区间。
做法是,按照右端点从小到大排序,不需要管左端点。
选择第一条线段,然后第3.4条。那么假设我们不选第一条线段,选择第二条,是否会
更优呢?我们发现第二条线段比第一条凸出一部分,这就导致再选择下一条线段时对于左
端点的要求更高。也就是必须要左端点更靠右。那么对于本题,线段有了权值。对于一群
小怪兽来说,到底是上1只,还是2只,还是全上,还是一个都不上呢?
假设现在公交车的容积为3,假设对于第1群怪兽为线段1,有3只怪兽
我只让2只怪兽上车,那么还有一个空座,让第二群怪兽上来一个
为线段2,图上标注好了上下车距离。那么看出第一群怪兽到底是全上
还是上2个,第二群上一个呢。发现,第一群怪兽全上是更优的,因为
同样是运3只怪兽,如果第1群上2个,第2群比第一群的路线凸出来很多,
占更多的座位。好了,到目前为止贪心的策略为能上就上。
设f[i]为第i个点对于第P群怪兽,看看这一群能上几只怪兽,就要求出
这群怪兽的行程的起点到终点的一段区间内的最大值。然后计算最多
能上几只怪兽。然后修改f数组。发现这是一个区间求最大值,区间修改
的操作,线段树可以维护。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 200005
using namespace std; int k,n,m,ans;
struct Tree{
int l,r,sum,s;
}tr[maxn<<];
struct GS{
int x,y,c;
bool operator < (const GS &a) const{
return y<a.y;
}
}a[maxn*]; void pushup(int rt){
tr[rt].sum=max(tr[rt<<].sum,tr[rt<<|].sum);
return;
} void pushdown(int rt){
if(!tr[rt].s)return;
tr[rt<<].s+=tr[rt].s;tr[rt<<|].s+=tr[rt].s;
tr[rt<<].sum+=tr[rt].s;tr[rt<<|].sum+=tr[rt].s;
tr[rt].s=;
} void build(int rt,int l,int r){
tr[rt].l=l;tr[rt].r=r;
if(l==r)return;
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
} int query(int rt,int l,int r,int qx,int qy){
pushdown(rt);
if(l>=qx&&r<=qy){
return tr[rt].sum;
}
int mid=(l+r)>>;
if(qy<=mid)return query(rt<<,l,mid,qx,qy);
else if(qx>mid)return query(rt<<|,mid+,r,qx,qy);
else return max(query(rt<<,l,mid,qx,mid),query(rt<<|,mid+,r,mid+,qy));
} void change(int rt,int l,int r,int qx,int qy,int z){
pushdown(rt);
if(l>=qx&&r<=qy){
tr[rt].sum+=z;
tr[rt].s+=z;
return;
}
int mid=(l+r)>>;
if(qy<=mid)change(rt<<,l,mid,qx,qy,z);
else if(qx>mid)change(rt<<|,mid+,r,qx,qy,z);
else change(rt<<,l,mid,qx,mid,z),change(rt<<|,mid+,r,mid+,qy,z);
pushup(rt);
} int main(){
scanf("%d%d%d",&k,&n,&m);
for(int i=;i<=k;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);
sort(a+,a+k+);
for(int i=;i<=k;i++){
int p=min(a[i].c,m-query(,,n,a[i].x,a[i].y-));
if(p){
ans+=p;
change(,,n,a[i].x,a[i].y-,p);
}
}
printf("%d\n",ans);
return ;
}
AC
解谜游戏(puzzle)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK进了一家古董店,它很想买其中的一幅画。但它带的钱不够买这幅画。
幸运的是,老板正在研究一个问题,他表示如果LYK能帮他解出这个问题的话,就把这幅画送给它。
老板有一个n*m的矩阵,他想找一个和最大的子矩阵,这个子矩阵可以由四个参数x,y,x2,y2(1<=x<=x2<=n,1<=y<=y2<=m)来表示,表示一个左上角为(x,y),右下角为(x2,y2)的矩阵。
为了让游戏更加有趣,老板给了一个常数P,他想将原来这个矩阵中恰好一个数变为P,使得这个矩阵的最大的子矩阵尽可能大。
老板想知道这个最大值是多少。
你能帮帮LYK吗?
输入格式(puzzle.in)
第一行三个数n,m,P。
接下来n行,每行m个数ai,j描述整个矩阵。
输出格式(puzzle.out)
输出一个数表示答案。
输入样例
3 3 3
-100 3 3
3 -4 3
3 3 3
输出样例
20
样例解释
改变左上角那个数。
数据范围
对于20%的数据n,m<=10。
对于40%的数据n,m<=25。
对于60%的数据n,m<=50。
对于80%的数据n,m<=100。
对于100%的数据1<=n,m<=300,|P|,|ai,j|<=1000。
题解:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; int n,m,p,ans;
int sum[][],a[][]; bool init(int x,int y,int zx,int zy,int yx,int yy){
if(x>=zx&&x<=yx&&y>=zy&&y<=yy)return true;
return false;
} int main(){
freopen("puzzle.in","r",stdin);
freopen("puzzle.out","w",stdout);
scanf("%d%d%d",&n,&m,&p);
//n行m列改成p
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&a[i][j]);
sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+a[i][j];
}
}
ans=-0x7ffffff;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
for(int h=;h<=m;h++){
for(int l=;l<=n;l++){
for(int u=;u+l-<=n;u++){
for(int v=;v+h-<=m;v++){
int hang=u+l-,lie=v+h-;
int all=sum[hang][lie]-sum[hang][v-]-sum[u-][lie]+sum[u-][v-];
if(init(i,j,u,v,hang,lie))
ans=max(ans,all-a[i][j]+p);
else ans=max(ans,all);
}
}
}
}
}
}
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
前缀和优化暴力40
正解:dp
先看一个经典问题,求一个序列的最大子段和。我们是可以O(n)求的。
dp转移方程:f[i]=max(f[i-1]+a[i],a[i]) 对于每个数字,它可以加入前一段也可以单独一块。
那么对于要求修改一次的序列呢?假如要求把a[i]->p
f[i][0]=max(f[i-1][0]+a[i],a[i])和f[i][1]=max{f[i-1][0]+p,p,f[i-1][1]+a[i]}
我们可以求出矩阵每一列的前缀和,枚举子矩阵的上下边界,a[i]=矩阵这
一列上下界之前的和,那么这个问题就和我们开始的经典问题没有差别了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 1000000000
using namespace std; int n,m,p,ans,map[][],sum[][],mn[],a[],dp[][]; int main(){
scanf("%d%d%d",&n,&m,&p);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&map[i][j]);
sum[i][j]=map[i][j];
sum[i][j]+=sum[i-][j];
}
}
for(int tu=;tu<=n;tu++){
for(int i=;i<=m;i++)mn[i]=map[tu][i];
for(int td=tu;td<=n;td++){
for(int i=;i<=m;i++)mn[i]=min(mn[i],map[td][i]);
for(int i=;i<=m;i++)a[i]=sum[td][i]-sum[tu-][i];
dp[][]=-inf;
for(int i=;i<=m;i++){
dp[i][]=max(dp[i-][]+a[i],a[i]);
dp[i][]=max(max(dp[i-][]+a[i],a[i]-mn[i]+p),dp[i-][]-mn[i]+p+a[i]);
}
if(tu==&&td==n)ans=max(ans,dp[m][]);
else for(int i=;i<=m;i++)ans=max(ans,max(dp[i][],dp[i][]));
}
}
printf("%d\n",ans);
return ;
}
AC
2017.10.3北京清北综合强化班DAY3的更多相关文章
- 2017.10.4北京清北综合强化班DAY4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- 2017.10.7北京清北综合强化班DAY7
1.计数 (count.cpp/c/pas) 时间限制:1s 内存限制:256MB [问题描述] 给出m个数a[1],a[2],…,a[m] 求1~n中有多少数不是a[1],a[2],…,a[m]的倍 ...
- 2017.10.6北京清北综合强化班DAY6
题目大意:改变一个数的位置 把一个序列变成不下降序列 题解: 设置一个pre,如果破坏单调性,就把‘删除’这个.否则把pre修改为当前元素的值. 考试时这样得了90分,是因为我的做法只能过这样的数据 ...
- 2017.10.5北京清北综合强化班DAY5
拼不出的数lost.in/.out/.cpp[问题描述]3 个元素的集合{5, 1,2} 的所有子集的和分别是0,1, 2, 3, 5, 6, 7, 8.发现最小的不能由该集合子集拼出的数字是4.现在 ...
- 2017.10.1北京清北综合强化班DAY1
a[问题描述]你是能看到第一题的 friends 呢.——hja何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx. 何大爷今天为字符串定义了新的权值计算方法.一个字符串 由小写字母组成,字符串 ...
- 2017.10.2北京清北综合强化班DAY2
a[问题描述]你是能看到第一题的 friends呢. —— hja世界上没有什么比卖的这 贵弹丸三还令人绝 ...
- 北京清北 综合强化班 Day3
括号序列(bracket) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法的 ...
- 北京清北 综合强化班 Day4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- 北京清北 综合强化班 Day2
a [问题描述] 你是能看到第一题的 friends呢. —— hja世界上没有什么比卖的这 贵弹丸三还令 ...
随机推荐
- iOS 11 Xcode9开发 新特性学习 (警告篇)
最新版本SDK优化了开发体验,编译过程会提供更多提示警告,建议你修改.这些功能也可以自主选择用或者不用,当然,苹果喜欢你用他推荐的东西... 1 . @avalibale 语法,同步判断当前iOS系统 ...
- UI控件之UITableView的基本属性
UITableView:特殊的滚动视图,横向固定,可以在纵向上滚动,自动计算contentSize 创建tableView,初始化时指定样式,默认是plain UITableView *_tableV ...
- arcgis flex aqi 3大util
第一:webMapUtil 主要用来根据id或者json创建map,跟webmap相关 第二:GeometryUtil 主要用来计算面积,长度,还有判断是否相交等,跟geometry相关. 第三:We ...
- SQL 根据IF判断,SET字段值
当INVOICE_STATUS值为1时,赋值为2,否者赋值为原来的值 UPDATE T_INVOICE SET DOWNLOAD_COUNT = DOWNLOAD_COUNT + 1, INVOICE ...
- lambda可调用对象
//find_if谓词使用 bool isShorter(const string &s1, const string &sz){ return s1.size() < sz.s ...
- 线性代数:Ax=b的解
n列的矩阵A,当且仅当向量b是列空间C(A)的一个向量时,Ax=b有解. C(A)的零空间是N(A),N(A)正交补是A的行空间C(T(A)), 依据上一章的结论,任何Rn向量可以表示为r+n,其中n ...
- c++ boost库学习二:内存管理->智能指针
写过C++的人都知道申请和释放内存组合new/delete,但同时很多人也会在写程序的时候忘记释放内存导致内存泄漏.如下所示: int _tmain(int argc, _TCHAR* argv[]) ...
- JavaWeb -- 文件上传下载示例
1. 上传简单示例 Jsp <%@ page language="java" import="java.util.*" pageEncoding=&quo ...
- linux命令:mv命令
mv命令是move的缩写,可以用来移动文件或者将文件改名(move (rename) files),是Linux系统下常用的命令,经常用来备份文件或者目录. 1.命令格式: mv [选项] 源文件或目 ...
- JMeter接口测试报错,反馈和postman不一样(二)
我总共现在有两个可以学习的接口,昨天测试一个接口发现问题解决后,今天测试另外一个发现又有问题了 这一次还是反馈显示不一样 要么 这种情况是直接从postman里面拿过来的数据,没做处理 报not j ...