题解:

贪心+dp

30% N<=5  5!枚举一下

20%  高度没有的时候,高度花费就不存在了,将ci排序,

从小到大挨个跳。另外,20% 准备跳楼没有花费,那么跳

楼的高度一定是从小到大,或者是从大到小。所以按照hi从

小到大排序,那么跳楼一定是排序后连续的一段。枚举第一

栋楼从哪开始跳。对于100% (1)hi从小到大排序,最后高度

的花费一定是hend-hstart。那么start—end中间楼的高度就

不会造成影响,只需要将start—end中间的楼排序,取小的ci。

(2)现在跳在第i栋楼上,已经跳了j栋楼了的最小花费。

f[i][j]—>min{ f[k][j+1]+c[k]+abs{h[i]-h[k]} }

最后答案是枚举i,j。

代码:

暴力挂了20

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 60
using namespace std; int n,t,ans,flag1,flag2,flag3;
int vis[maxn]; struct Build{
int h,c;
}b[maxn]; inline int read(){
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';
return x*f;
} bool cmp1(Build a,Build b){
return a.c<b.c;
} bool cmp2(Build a,Build b){
return a.h<b.h;
} void dfs(int nxt,int now,int sum){
sum+=b[now].c;
if(sum>t)return;
ans=max(ans,nxt-);
for(int i=;i<=n;i++){
if(vis[i]==){
vis[i]=;
if(nxt==){
dfs(nxt+,i,sum);
vis[i]=;
}else {
dfs(nxt+,i,sum+abs(b[now].h-b[i].h));
vis[i]=;
}
}
}
return;
} int main(){
freopen("meet.in","r",stdin);
freopen("meet.out","w",stdout);
n=read();flag1=true;flag2=true;
for(int i=;i<=n;i++)b[i].c=read();
for(int i=;i<=n;i++)b[i].h=read();
t=read();
if(n<=){
dfs(,,);
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
for(int i=;i<=n;i++){
if(b[i].h!=b[i-].h){
flag1=false;break;
}
}
if(flag1){
int ret=;
sort(b+,b+n+,cmp1);
for(int i=;i<=n;i++){
if(t-b[i].c>){
ret++;t-=b[i].c;
}
}
printf("%d\n",ret);
fclose(stdin);fclose(stdout);
return ;
}
for(int i=;i<=n;i++){
if(b[i].c){
flag2=false;break;
}
}
if(flag2){
sort(b+,b+n+,cmp2);
for(int len=;len<=n;len++){
flag3=false;
for(int st=;st+len-<=n;st++){
int ed=st+len-,pre=b[st].h,f=;
for(int i=st;i<=ed;i++){
f+=b[i].h-pre;
pre=b[i].h;
}
if(f<=t)flag3=true,ans=max(ans,len);
}
if(flag3==false)break;
}
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
dfs(,,);
printf("%d\n",ans);
fclose(stdin);fclose(stdout);
return ;
}

50

正解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,t,ans;
int f[][]; struct Build{
int c,h;
bool operator < (const Build &a) const{
h<a.h;
}
}a[]; int main(){
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i].c);
for(int i=;i<=n;i++)scanf("%d",&a[i].h);
scanf("%d",&t);
sort(a+,a+n+);
memset(f,0x3f,sizeof(f));
for(int i=;i<=n;i++)f[i][]=a[i].c;
for(int i=;i<=n;i++)
for(int j=;j<=i;j++){
for(int k=;k<i;k++)
f[i][j]=min(f[i][j],f[k][j-]+(j==?:a[i].h-a[k].h)+a[i].c);
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(f[i][j]<=t)ans=max(ans,j);
printf("%d\n",ans);
return ;
}

AC

题解:

假设

a1<a2<a3.....<an

b1<b2<b3...<b(n*(n-1)/2)

那么b1=a1+a2,b2=a1+a3....

a2+a3=bx,然后枚举bx,

根据

a1+a2=b1

a1+a3=b2

a2+a3=bx,

三个方程三个未知数,在b数组中删去b1,b2,bx,

那么b数组中剩下最小的一定是

a1+a4,a2+a4,a3+a4....都知道了,然后从b数组中删去。

重复上步。

代码还明白。

v#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> using namespace std; const int maxn=; int n,m,res[maxn],ans[maxn][maxn],z[maxn*maxn],cnt; bool use[maxn*maxn]; void check(int p)
{
memset(use,false,sizeof(use));
if ((z[]+z[]+z[p])&) return;
res[]=(z[]+z[]+z[p])/-z[p];
res[]=z[]-res[];
res[]=z[]-res[];
use[]=use[]=use[p]=true;
for (int a=,b=;a<=n;a++)
{
while (b<=m && use[b])
b++;
if (b>m) return;
res[a]=z[b]-res[];
use[b]=true;
for (int c=;c<a;c++)
{
if (res[c]>res[a]) return;
int v=res[c]+res[a];
int p=lower_bound(z+,z+m+,v)-z;
if (z[p]!=v) return;
int px=p;
while (px && z[px]==z[p])
px--;
px++;
while (px<=m && z[px]==z[p] && use[px])
px++;
if (z[px]!=z[p] || use[px]) return;
p=px;
use[p]=true;
}
}
cnt++;
for (int a=;a<=n;a++)
ans[cnt][a]=res[a];
} int main()
{
freopen("city.in","r",stdin);
freopen("city.out","w",stdout); scanf("%d",&n);
m=n*(n-)/;
for (int a=;a<=m;a++)
scanf("%d",&z[a]);
sort(z+,z+m+);
for (int a=;a<=m;)
{
check(a);
int b=a;
while (b<=m && z[b]==z[a])
b++;
a=b;
}
printf("%d\n",cnt);
for (int a=;a<=cnt;a++)
for (int b=;b<=n;b++)
{
printf("%d",ans[a][b]);
if (b==n) printf("\n");
else printf(" ");
} return ;
}

std

 题解:

又写挂的暴力.

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100009
#define maxm 70009
using namespace std; int n,m,gg,cnt,ans,pp;
int a[maxn],sum[][],p[]; struct Q{
int l,r,v,id;
}q[maxn]; inline int read(){
int x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';
return x*f;
} void slove1(){
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=m;i++){
int l,r,p,v,ans=;
l=read();r=read();p=read();v=read();
for(int j=l;j<=r;j++)
if(a[j]%p==v)ans++;
printf("%d\n",ans);
}
} void slove2(){
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=m;i++){
q[i].l=read();q[i].r=read();pp=read();q[i].v=read();
}
for(int i=;i<=n;i++){
a[i]%=pp;if(!p[a[i]])p[a[i]]=++cnt;
}
for(int i=;i<=n;i++){
for(int j=;j<=cnt;j++)sum[i][j]=sum[i-][j];
sum[i][p[a[i]]]++;
}
for(int i=;i<=m;i++){
int L=q[i].l,R=q[i].r,V=q[i].v;
printf("%d\n",sum[R][p[V]]-sum[L-][p[V]]);
}
} int main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
n=read();m=read();
if(n<=&&m<=){
slove1();
fclose(stdin);fclose(stdout);
return ;
}else
slove2();
fclose(stdin);fclose(stdout);
return ;
}

30

正解:下面是自己都mengbi的笔记

暴力30%

P相同的30%,将ai%p的值存在vector里。

每次询问时寻找vector,用个数据结构维护一下。

1 5 2 3 4   q=3

1 2 2 0 1

V=0  4

V=1  1 5

V=2  2 3

二分找。空间大小是O(n),可以用vector去搞。

100%做法

对于每一个p需要处理每一个数%p之后在0—n-1的哪一个位置。

100%的数据和之前的区别是p不一样了是吧。只考虑p<=10^4。

可以对每一个p做一个预处理,然后建一个0—n-1的数组,每个p有个O(n)的

空间,那么有O(np),会TLE。所以不能对所有的p进行处理。那么对哪些p进

行处理呢?可以对1<=p<=100,进行处理。对于1<=p<=100,套用60%的做法,

像之前预处理,空间100*n,询问去数组里二分找就可以了。P>100怎么做呢?

我们不可能对那么多p进行处理,考虑每个询问,l-r,能被统计进答案的数是哪些?

是v,v+p,v+2p…..V+KP<=10^4,p>100,那么k<100,说明不到100个数。求p+kv

在l—r中出现了多少次????在数组里二分求。就是把60%的模p改成不模p。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> using namespace std; const int maxn=; int n,m,res[maxn],ans[maxn][maxn],z[maxn*maxn],cnt; bool use[maxn*maxn]; void check(int p)
{
memset(use,false,sizeof(use));
if ((z[]+z[]+z[p])&) return;
res[]=(z[]+z[]+z[p])/-z[p];
res[]=z[]-res[];
res[]=z[]-res[];
use[]=use[]=use[p]=true;
for (int a=,b=;a<=n;a++)
{
while (b<=m && use[b])
b++;
if (b>m) return;
res[a]=z[b]-res[];
use[b]=true;
for (int c=;c<a;c++)
{
if (res[c]>res[a]) return;
int v=res[c]+res[a];
int p=lower_bound(z+,z+m+,v)-z;
if (z[p]!=v) return;
int px=p;
while (px && z[px]==z[p])
px--;
px++;
while (px<=m && z[px]==z[p] && use[px])
px++;
if (z[px]!=z[p] || use[px]) return;
p=px;
use[p]=true;
}
}
cnt++;
for (int a=;a<=n;a++)
ans[cnt][a]=res[a];
} int main()
{
freopen("city.in","r",stdin);
freopen("city.out","w",stdout); scanf("%d",&n);
m=n*(n-)/;
for (int a=;a<=m;a++)
scanf("%d",&z[a]);
sort(z+,z+m+);
for (int a=;a<=m;)
{
check(a);
int b=a;
while (b<=m && z[b]==z[a])
b++;
a=b;
}
printf("%d\n",cnt);
for (int a=;a<=cnt;a++)
for (int b=;b<=n;b++)
{
printf("%d",ans[a][b]);
if (b==n) printf("\n");
else printf(" ");
} return ;
}

std

题解:贪心

遇到右括号和待匹配的左括号匹配。没有待匹配的左括号那么

将这个右括号改成左括号。最后将剩余的左括号一半改成右括

号进行匹配。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100009
using namespace std; char s[maxn];
int len,top,ans; int main(){
freopen("shower.in","r",stdin);
freopen("shower.out","w",stdout);
scanf("%s",s+);len=strlen(s+);
for(int i=;i<=len;i++){
if(s[i]=='(')top++;
else {
if(top)top--;
else ans++,top++;
}
}
printf("%d\n",ans+top/);
fclose(stdin);fclose(stdout);
return ;
}

AC

题解:线性筛+前缀和+二分

那么求连续k个质数的和就是O(1)的了。

发现,在前面选k个比在后面选k个小,这说明是有单调性的,二分k个

数最后一个数的位置。也可以二分第一个数。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000009
#define LL long long
using namespace std; LL n;
int t,k,cnt;
int check[maxn],prime[maxn];
LL sum[maxn]; inline LL read(){
LL x=,f=;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';
return x*f;
} void Prime(){
check[]=true;
for(int i=;i<=;i++){
if(!check[i])prime[++cnt]=i,sum[cnt]=sum[cnt-]+i;
for(int j=;j<=cnt&&i*prime[j]<=;j++){
check[i*prime[j]]=true;
if(i%prime[j]==)break;
}
}
} int main(){
freopen("diary.in","r",stdin);
freopen("diary.out","w",stdout);
scanf("%d",&t);
Prime();
for(int i=;i<=t;i++){
n=read();scanf("%d",&k);
int l=,r=cnt;
LL ans=;
while(l<=r){
int mid=(l+r)>>;
int p=mid-k;
if(p>=){
LL gg=sum[mid]-sum[p];
if(gg<=n){
ans=gg;
l=mid+;
}else r=mid-;
}else l=mid+;
}
if(ans==)printf("-1\n");
else printf("%I64d\n",ans);
}
fclose(stdin);fclose(stdout);
return ;
}

AC

题解:

30%暴力建树+floyed

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define mod 1000000007
using namespace std; int m,a,b,c,d,l;
int tree[][][],node[]; void make_tree(int k){
LL ans=;
int num=node[a];node[k]=node[a]+node[b];
for(int i=;i<=node[a];i++)
for(int j=;j<=node[a];j++)
tree[k][i][j]=tree[a][i][j];
for(int i=;i<=node[b];i++)
for(int j=;j<=node[b];j++)
tree[k][i+num][j+num]=tree[b][i][j];
tree[k][c][num+d]=tree[k][num+d][c]=l;
for(int kk=;kk<=node[k];kk++)
for(int i=;i<=node[k];i++)
for(int j=;j<=node[k];j++)
tree[k][i][j]=min(tree[k][i][j],tree[k][i][kk]+tree[k][kk][j]);
for(int i=;i<=node[k];i++)
for(int j=i+;j<=node[k];j++)
ans=(ans%mod+tree[k][i][j]%mod)%mod;
printf("%I64d\n",ans);
} int main(){
freopen("cloth.in","r",stdin);
freopen("cloth.out","w",stdout);
scanf("%d",&m);node[]=;
memset(tree,0x3f,sizeof(tree));
for(int i=;i<=;i++)
for(int j=;j<=;j++)
tree[i][j][j]=;
for(int i=;i<=m;i++){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&l);
c++;d++;
make_tree(i);
}
fclose(stdin);fclose(stdout);
return ;
}

40

60%是让你线性树形dp的

下面是我记的笔记..具体在写什么我也mengbi了。

发现是由左边的树和右边的树拼起来的,那么答案肯定有左边和右边的答案。

F(TI)=F(TJ)+F(TK)+?

肯定包括左边内部距离和右边内部距离。

?就是左边的点到右边的点的距离。

具体考虑怎样算这一部分。

看L会走size[j]*size[k]*L

G[j][p1]第j棵树所有点到p1的距离之和。

Size[j]*G[k][p2]+size[j]*size[k]*l+size[k]*G[j][1]

Size[]在合并的时候就可以求出Size的大小。

关键是G[j][p]怎么求?可以分成两部分来求。

第I棵树中所有点到p的距离,是第j棵树到p的距离和第k

树到p的距离的和。那么第K棵树到所有点的距离到底怎么算。

首先右边某点到左边,l和dis[p1][p]是不变的。

(l+dis[i][p][p1])第i棵树p到p1的距离。

G[i][p]的第二维有2^m种可能。算不了..空间大…会炸….

记忆化搜索,没必要求出所有的,把连起来的那两个算出来就可以了。

代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map> using namespace std; const int mo=;
const int maxn=; int n,id1[maxn],id2[maxn],l[maxn],res[maxn]; long long num1[maxn],num2[maxn],size[maxn]; struct rec
{
int p;
long long p1,p2;
rec(){}
rec(int a,long long b,long long c)
{
p=a;
if (b<c) p1=b,p2=c;
else p1=c,p2=b;
}
bool operator<(const rec &a)const
{
if (p!=a.p) return p<a.p;
if (p1!=a.p1) return p1<a.p1;
return p2<a.p2;
}
}; map< pair<int,long long > ,int > ma; map<rec,int> ma2; int solve(int p,long long p1,long long p2)
{
if (!p) return ;
if (p1==p2) return ;
rec x=rec(p,p1,p2);
if (ma2.count(x)) return ma2[x];
if (p1<size[id1[p]])
{
if (p2<size[id1[p]]) ma2[x]=solve(id1[p],p1,p2);
else ma2[x]=((long long)solve(id1[p],num1[p],p1)+solve(id2[p],num2[p],p2-size[id1[p]])+l[p])%mo;
}
else
{
if (p2<size[id1[p]]) ma2[x]=((long long)solve(id1[p],num1[p],p2)+solve(id2[p],num2[p],p1-size[id1[p]])+l[p])%mo;
else ma2[x]=solve(id2[p],p1-size[id1[p]],p2-size[id1[p]]);
}
return ma2[x];
} int solve(int p,long long n)
{
if (p==) return ;
pair<int,long long> px;
px=make_pair(p,n);
if (ma.count(make_pair(p,n))) return ma[px];
if (n<size[id1[p]]) ma[px]=(((long long)solve(id1[p],num1[p],n)+l[p])*(size[id2[p]]%mo)%mo+solve(id2[p],num2[p])+solve(id1[p],n))%mo;
else ma[px]=(((long long)solve(id2[p],num2[p],n-size[id1[p]])+l[p])*(size[id1[p]]%mo)%mo+solve(id1[p],num1[p])+solve(id2[p],n-size[id1[p]]))%mo;
return ma[px];
} int main()
{
freopen("cloth.in","r",stdin);
freopen("cloth.out","w",stdout); while (~scanf("%d",&n))
{
ma.clear();
ma2.clear();
for (int a=;a<=n;a++)
scanf("%d%d%I64d%I64d%d",&id1[a],&id2[a],&num1[a],&num2[a],&l[a]);
size[]=;
for (int a=;a<=n;a++)
size[a]=size[id1[a]]+size[id2[a]];
for (int a=;a<=n;a++)
res[a]=((long long)solve(id1[a],num1[a])*(size[id2[a]]%mo)%mo+(long long)(size[id1[a]]%mo)*(size[id2[a]]%mo)%mo*l[a]%mo+(long long)solve(id2[a],num2[a])*(size[id1[a]]%mo)%mo+res[id1[a]]+res[id2[a]])%mo;
for (int a=;a<=n;a++)
printf("%d\n",res[a]);
}
return ;
}

std

小结:

上午 :

预计分数:70+0+60

实际得分:50+0+30

下午:

预计分数:100+100+30

实际得分:100+100+40

反思:

上午一直想最后一题后30%的暴力,前缀和

能MLE,侥幸尽量开大数组....结果一分没有....

再也不写玄学暴力了....

下午还好...题有点水...

T1做过秒过...T2想了想就秒了...

T3...一脸bengbi...暴力都不会写...怎么存图什么的...

想了半天...硬着头皮写还是很好写的....

早上吃多了一天都撑的难受..【哭唧唧QAQ

noip济南清北冲刺班DAY2的更多相关文章

  1. noip济南清北冲刺班DAY1

    上午 T1 立方数 题目描述 LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数. 现在给定一个数P,LYK想要知道这个数 ...

  2. 济南清北学堂游记 Day 1.

    快住手!这根本不是暴力! 刷了一整天的题就是了..上午三道题的画风还算挺正常,估计是第一天,给点水题做做算了.. rqy大佬AK了上午的比赛! 当时我t2暴力写挂,还以为需要用啥奇怪的算法,后来发现, ...

  3. 济南清北学堂游记 Day 0.

    (摄于千佛山山顶,济南城区风光) 看似稳得一比,实则慌如老狗= = 我可能是报到最早的且实力最弱的一只. 早晨六点二十被从床上拉起来,然后在火车站附近匆忙吃了点东西就坐火车去济南了. 路途不算远,大概 ...

  4. 济南清北学堂游记 Day 6.

    还剩一天半我就该回去了. 说实话今天挺可惜的,有很多本来可以得到的分数评测时没有拿到.上午的第一题和第二题我都想出了正解,T3敲了一个暴力,虽然暴力写坏了.预计是可以拿210的但是实际上只有很少的分数 ...

  5. 济南清北学堂游记 Day 5.

    十一月的第一天.算下来在济南已经呆了接近一星期了...... 还剩九天...看着洛谷的倒计时心里直发慌. 也许我不该过多纠结于高级算法,基础也是很重要的. 今天晚上就自由的敲一些板子吧.最后的九天,让 ...

  6. 济南清北学堂游记 Day 2.

    在大佬云集的地方被直线碾压是什么样的体验? 大概就是210和1030的差别. 大概就是高质量机械键盘和空气的区别. 回来的路上,我一直在想,我到底是不是一个高三的? 大概也是能找到以前在家和学校训练时 ...

  7. 清北暑假模拟day2 将

    /* 爆搜,正解弃坑 */ #include<iostream> #include<cstdio> #include<string> #include<cst ...

  8. 清北暑假模拟day2 之

    /* 现场代码,枚举每条边删除 */ #include<iostream> #include<cstdio> #include<string> #include&l ...

  9. 清北暑假模拟day2 国

    [题目描述]在世界的东边,有三瓶雪碧.--laekov黎大爷为了虐 zhx,给 zhx 出了这样一道题.黎大爷搞了一个数据结构,但是他没有告诉 zhx 这到底是什么数据结构,我们只知道这是一个数据结构 ...

随机推荐

  1. Boot-Repair&usb_repair

    https://help.ubuntu.com/community/Boot-Repair https://askubuntu.com/questions/500647/unable-to-mount ...

  2. shell检查网络出现异常、僵尸进程、内存过低后,自动重启

    #!/bin/bash while : do neterror=$(/bin/netstat -a | grep -cw "CLOSE_WAIT") echo "get ...

  3. linux 查看内存信息,及其他硬件信息 dmidecode命令

    由于想换内存,想看看内存型号.频率,简单搜了下命令 可以用dmidecode 命令查看. dmidecode -t memory 这个命令可以查看内存的几乎所有信息,包括频率 大小等等 另外这个命令强 ...

  4. 20145219 《Java程序设计》第09周学习总结

    20145219 <Java程序设计>第09周学习总结 教材学习内容总结 JDBC入门 JDBC简介 1.JDBC是java联机数据库的标准规范,它定义了一组标准类与接口,应用程序需要联机 ...

  5. 总结一下TODO的用法

      1.设置任务的标签 WINDOW->preference->java->complier->task tags加一个 DONE:NORMAL表示已经完成的任务2. java ...

  6. 洛谷P4311 士兵占领

    题目描述 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵 ...

  7. 如何在MyEclipse中更改servlet模板 Jsp模板

    http://blog.csdn.net/sjw890821sjw/article/details/6995190 刚换上Myeclipse9.0,结果要修改servlet模板的时候不像Myeclps ...

  8. 列出远程git的全部分支

    列出全部分支 git ls-remote --heads your.git | awk 'sub(/refs\/heads\//,""){print $2}' 其中awk中sub替 ...

  9. Eclipse Android 代码自动提示功能

    Eclipse Android 代码自动提示功能 Eclipse for android 实现代码自动提示智能提示功能,介绍 Eclipse for android 编辑器中实现两种主要文件 java ...

  10. struts中操作request,session

    在Action类中操作request,session 方法一.利用ActionContext.getContext().get("request"); //返回的是Map集合 Ma ...