NOIP2011提高组
D1T1.铺地毯
for循环
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct hp{
int a,b,g,k;
}map[];
int main()
{
int n,i,x,y;
cin>>n;
for(i=;i<=n;i++)
cin>>map[i].a>>map[i].b>>map[i].g>>map[i].k;
cin>>x>>y;
for(int i=n;i>=;i--)
{
if(map[i].a<=x&&map[i].a+map[i].g>=x&&map[i].b<=y&&map[i].b+map[i].k>=y)
{cout<<i<<endl;return ;}
}
cout<<"-1"<<endl;
return ;
}
D1T2.选择客栈
这道题O(kn)算法很简单啊,我来讲讲O(n)的算法吧
a[c]表示记录到第i个客栈为止色调为c的客栈的总数
b[c]表示记录到离当前客栈i最近的消费水平不高于p的客栈为止色调为c的客栈的数量
s[c]记录到当前客栈i为止,最后一个色调为c的客栈的编号
f记录距离客栈i最近的消费水平不超过p的客栈的编号
每读入一个客栈的色调c和最低消费v,我们首先来判断v是否超过了p,如果v没有超过p的话,我们让f=i,即先更新f。
每读入一组数据c和v,我们就应该更新a[c]和s[c],但是在这一步之前,我们要做如下操作:
不管当前客栈i的消费水平如何,我们来比较f和最后一个色调为c的客栈的编号s[c]的大小关系,
由于我们还没有更新s[c],所以这次比较不包含当前客栈i;
对于当前客栈i的色调c来说,如果该色调是在编号为f的客栈之后第一次出现,则必有f>=s[c],那么a[c]里面记录的必然是在f客栈之前(包括f)色调为c的客栈的数量,这时我们让b[c]=a[c],
如果色调c在客栈f之后出现的次数多于1次,那么我们必然已经更新过s[c],那么必然有s[c]>f,这时我们不做任何操作,则b[c]内保存的依然是在客栈f之前(包括f)色调为c的客栈的数量。
在这里,f发生变化与否,对结果是没有影响的,因为即便在这一步之前f发生了变化,如果某个色调c一直没有出现的话,那对结果没有任何影响,
而一旦某个色调在f变化之后第一次出现,必然有f>=s[c],这时必然要更新b[c],那么b[c]必然在这里就会更新成为我们后面计算需要的正确的值,而且在f再次变化之前,b[c]将保持不变。
#include<cstdio>
int a[],b[],s[],f=,n,k,p,c,v,ans=;
int main()
{
scanf("%d%d%d",&n,&k,&p);
for(int i=;i<=n;i++)
{
scanf("%d%d",&c,&v);
if(v<=p)f=i;
if(f>=s[c])b[c]=a[c];
ans+=b[c];a[c]++;s[c]=i;
}
printf("%d",ans);
return ;
}
D1T3 Mayan游戏
搜索+剪枝
1.因为1优先于-1,所以如果一个方块左边也有方块,那么不用搜索这个状态
2.直接从地图的左下角按从下到上,从左到右的顺序搜索
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
bool ret=;
int mp[][],n,ansx[],ansy[],ansg[];
void diao()
{
int w[];memset(w,,sizeof(w));
for(int j=;j<=;j++)
for(int i=;i>=;i--)
{
if(!mp[i][j]){w[j]=i;break;}
}
for(int i=;i>=;i--)
for(int j=;j<=;j++)
{
if(mp[i][j])
{
if(i>w[j])continue;
mp[w[j]][j]=mp[i][j];mp[i][j]=;w[j]--;
}
}
}
bool xiao()
{
int _mp[][];bool ok=;
for(int i=;i<=;i++)for(int j=;j<=;j++)_mp[i][j]=mp[i][j];
for(int i=;i<=;i++)
{
int j=;
while(j<=)
{
if(_mp[i][j]==){j++;continue;}int stop;
for(stop=j+;stop<=;stop++)if(_mp[i][stop]!=_mp[i][stop-])break;
if(stop-j>=){for(;j<stop;j++)mp[i][j]=;ok=;}
else j=stop;
}
}
for(int j=;j<=;j++)
{
int i=;
while(i<=)
{
if(_mp[i][j]==){i++;continue;}int stop;
for(stop=i+;stop<=;stop++)if(_mp[stop][j]!=_mp[stop-][j])break;
if(stop-i>=){for(;i<stop;i++)mp[i][j]=;ok=;}
else i=stop;
}
}
return ok;
}
void dfs(int t)
{
if(ret)return;
int _mp[][];
if(t>n)
{
bool ok=;
for(int i=;i<=;i++)
for(int j=;j<=;j++)if(mp[i][j])ok=;
if(!ok)
{
for(int i=;i<=n;i++)printf("%d %d %d\n",ansx[i],ansy[i],ansg[i]);
ret=;
return;
}
return;
}
int color[];memset(color,,sizeof(color));
bool ok=;
for(int i=;i<=;i++)for(int j=;j<=;j++)
{
_mp[i][j]=mp[i][j];color[mp[i][j]]++;if(mp[i][j])ok=;
}
if(!ok)return;
for(int i=;i<=;i++)if(color[i]>&&color[i]<)return;
for(int j=;j<=;j++)
for(int i=;i>=;i--)
{
if(mp[i][j]==)continue;
if(j!=)
{
swap(mp[i][j],mp[i][j+]);
do{
diao();
}while(xiao());
ansx[t]=j-;ansy[t]=-i;ansg[t]=;dfs(t+);
for(int i=;i<=;i++)for(int j=;j<=;j++)mp[i][j]=_mp[i][j];
}
if(j!=)
{
if(mp[i][j-]!=)continue;
swap(mp[i][j],mp[i][j-]);
do{
diao();
}while(xiao());
ansx[t]=j-;ansy[t]=-i;ansg[t]=-;dfs(t+);
for(int i=;i<=;i++)for(int j=;j<=;j++)mp[i][j]=_mp[i][j];
}
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
scanf("%d",&mp[-j][i]);if(!mp[-j][i])break;
}
dfs();
if(!ret)printf("-1");
return ;
}
D2T1 计算系数
杨辉三角
#include<iostream>
using namespace std;
int dp[][];const int mod=;
int main()
{
int a,b,k,n,m;scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
for(int i=;i<=k+;i++)dp[i][i]=,dp[i][]=;
for(int i=;i<=k+;i++)
for(int j=;j<i;j++)dp[i][j]=(dp[i-][j]+dp[i-][j-])%mod;
long long ans=dp[k+][m+];
for(int i=;i<=n;i++)ans=(ans*a)%mod;
for(int i=;i<=m;i++)ans=(ans*b)%mod;
cout<<ans;
return ;
}
D2T2 聪明的质检员
首先分析公式计算,容易发现sigma ci会随着 m 的递增单调递减。
因此答案满足了单调性,我们考虑二分答案 m,然后对于每次二分出来的答案check 的话,时间复杂度太高。
我们可以发现,可以使用前缀和来 O(1)回答区间查询,对于每个二分出来的 m,先花 O(n)的时间按题意做一下前缀和,然后再 O(q)计算一下 sigma,
这样的话就可以把每次二分完的 O(nq)优化到 O(n+q),总时间复杂度为O((n+q)log2S)
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int w[],v[],l[],r[],sw[],b[],c[];
int main()
{
int n,m;long long s;scanf("%d%d%lld",&n,&m,&s);
for(int i=;i<=n;i++){scanf("%d%d",&w[i],&v[i]);sw[i]=w[i];}
for(int i=;i<=m;i++)scanf("%d%d",&l[i],&r[i]);
sort(sw+,sw+n+);
long long ans=999999999999LL;int _l=,_r=n+;
while(_l<_r)
{
int mid1=(_l+_r)/;
int mid=sw[mid1];
b[]=;c[]=;
for(int i=;i<=n;i++)
{
int g=v[i];c[i]=c[i-];
if(w[i]<mid)g=;
else c[i]++;
b[i]=b[i-]+g;
}
long long x=;
for(int i=;i<=m;i++)x+=(b[r[i]]-b[l[i]-])*(c[r[i]]-c[l[i]-]);
if(x<s)_r=mid1;
else _l=mid1+;
ans=min(ans,abs(x-s));
}
printf("%lld",ans);
return ;
}
D2T3 观光公交
sum[i]:在前i站下车的人的总数;las[i]:最晚的一个人的到达i站的时间;get[i]最早的到达i站时间。
那么,题目所求的问题就是∑(get[b[i]]-t[i])。
可以转化为:∑(get[b[i]])-∑(t[i])。而∑(t[i])是定值,于是就是要使∑(get[b[i]])最小。
至于get[i],它取决于上一站的到站时间和最晚的一个人,get[i]=max(las[i-1],get[i-1])+d[i-1]。
容易想到,如果一个d[i]减小了,那么它肯定会影响到后面的一段连续的get[i]。
具体地来说,如果get[i]>las[i],也就是车的最早到达时间要晚于最慢的人的到达时间,那么前面如果用了加速器,那么就能使get[i]减小,否则就不能造成影响。
我们开一个数组g[i]表示如果d[i]减小,那么最多影响到后面的哪个站。很明显,随着d[i]的减小,g[i]是要变的。
g[i]=g[i+1](get[i+1]>las[i+1],后一个站的出发时间由到达时间决定) 或 i+1(get[i+1]<=las[i+1],后一个站的出发时间由最晚到达的人决定)。
要使加速器的效果最大,那么就要使这个加速器的作用影响到最多的人,于是每次找sum[g[i]]-sum[i]最大的一个d[i]加速(d[i]>0)。重复k次即可。
每一个加速器互不影响,所以不存在后效性,局部最优即是全局最优。
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,k,sum[],las[],get[],g[],ans=;
int d[],a[],b[],t[];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<n;i++)scanf("%d",&d[i]);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&t[i],&a[i],&b[i]);
las[a[i]]=max(las[a[i]],t[i]);sum[b[i]]++;
}
for(int i=;i<=n;i++)sum[i]+=sum[i-];
for(int i=;i<=n;i++)
{
get[i]=max(get[i-],las[i-])+d[i-];
}
g[n]=n;
for(int i=n-;i>=;i--)
{
if(get[i+]>las[i+])g[i]=g[i+];
else g[i]=i+;
}
for(int i=;i<=m;i++)ans+=get[b[i]]-t[i];
while(k)
{
int rs=,l,r;
for(int i=;i<n;i++)
{
if(sum[g[i]]-sum[i]>rs&&d[i])
{
rs=sum[g[i]]-sum[i];l=i;r=g[i];
}
}
d[l]--;ans-=rs;
for(int i=l;i<=r;i++)
{
get[i]=max(get[i-],las[i-])+d[i-];
}
if(r==n)r--;g[n]=n;
for(int i=r;i>=l;i--)
{
if(get[i+]>las[i+])g[i]=g[i+];
else g[i]=i+;
}
k--;
}
printf("%d",ans);
return ;
}
NOIP2011提高组的更多相关文章
- luogu1003铺地毯[noip2011 提高组 Day1 T1]
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...
- [NOIP2011] 提高组 洛谷P1312 Mayan游戏
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- [NOIP2011] 提高组 洛谷P1315 观光公交
题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2 ...
- [NOIP2011] 提高组 洛谷P1003 铺地毯
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...
- NOIP2011(提高组)DAY2---观光公交(vijosP1741)
描述 风景迷人的小城Y市,拥有n个美丽的景点.由于慕名而来的游客越来越多,Y市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第0分钟出现在1号景点,随后依次前往2.3.4……n号景 ...
- 洛谷-铺地毯-NOIP2011提高组复赛
题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于 ...
- 刷题总结——mayan游戏(NOIP2011提高组day2T3)
题目: 题目背景 NOIP2011提高组 DAY1 试题. 题目描述 Mayan puzzle 是最近流行起来的一个游戏.游戏界面是一个 7 行 5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即 ...
- 洛谷P1003 铺地毯 noip2011提高组day1T1
洛谷P1003 铺地毯 noip2011提高组day1T1 洛谷原题 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n ...
- [Luogu1313][NOIP2011提高组]计算系数
题目描述 给定一个多项式 (by+ax)k(by+ax)^k(by+ax)k ,请求出多项式展开后 xn×ymx^n \times y^mxn×ym 项的系数. 输入输出格式 输入格式: 共一行,包含 ...
- Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数
Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...
随机推荐
- 636. Exclusive Time of Functions
// TODO: need improve!!! class Log { public: int id; bool start; int timestamp; int comp; // compasa ...
- 【笔记】objdump命令的使用
---恢复内容开始--- objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它还有其他作用,下面以ELF格式可执行文件test为例详细介绍: objdump -f test 显示t ...
- python——int()函数
1. 使用 int() 将小数转换为整数,结果是向上取整还是向下取整呢? 小数取整会采用比较暴力的截断方式,即向下取整.(注:5.5向上取整为6,向下取整为5) 2. 我们人类思维是习惯于“四舍五入” ...
- C# 输出结果有System.Byte[]
byte[]类型直接输出或者调用ToString函数都会出现这个结果. 需要执行: byte[] a=new byte[10]; string text = "";for (int ...
- python-5模块
1-使用模块 import sys def test(): args = sys.argv if len(args)==1: print("hello word") elif le ...
- python-2函数
http://docs.python.org/3/library/functions.html 或者菜鸟中文资料 1-使用函数 abs(-20)#求绝对值 max(1,4,200,3,2) #求最大的 ...
- oracle11g导出表时空表导不出解决方案
oracle11g用exp命令导出数据库表时,有时会发现只导出了一部分表时而且不会报错,原因是有空表没有进行导出,之前一直没有找到方法于是用最笨的方法重新建这些空表,当然在我们实际当中表的数量大时我们 ...
- Android 数据库中的数据给到ListView
前言:因为之前学的都是用一个自己定义的类,完成将某一个bean中的数据直接获取,而实际中通常是通过数据库来得到的,总之,最终就是要得到数据.提一下最重要的东西,我把它叫做代理,如同一个校园代理,没有他 ...
- 15,Flask-Script
Flask-Script 从字面意思上来看就是 Flask 的脚本 是的,熟悉Django的同学是否还记得Django的启动命令呢? python manager.py runserver 大概是这样 ...
- bitset学习
bitset是个好东西.嗯.贼sao~ 很早就讲过但是我并没有弄懂.(现在也不敢说明白) 首先bitset是有常数的,而且常数并不能忽略不计——$(\frac{1}{32})$ 目前我也只是会bits ...