10.1日NOIP模拟赛

来源:互联网 发布:apache启动和停止命令 编辑:程序博客网 时间:2024/06/06 03:05

十月一日国庆狂欢!!题目大放送!

T1:最接近神的人

题目:

【问题描述】
因小CC平时不遵守规矩,被伟大的石老师下了符文之语,为了破解了符文之语,小CC不小心开启了通往地下的道路,当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案。而石门上方用古代文写着“神的殿堂”。小CC猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……。
仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最接近神明的。而最聪明的人往往通过一种仪式选拔出来。仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素。而用最少的交换次数使原序列变成不下降序列的人即是下一任智者。
小CC发现门上同样有着n个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小交换次数,但小CC不会……只好又找到了你,并答应事成之后与你三七分……。

【文件输入】
第一行为一个整数N,表示序列的长度
第二行为n个整数,表示序列中每个元素

【文件输出】
一个整数ans,即最少操作次数。

【样例输入】
4
2 8 0 3

【样例输出】
3

【样例说明】
开始序列为2 8 0 3,目标序列为0 2 3 8,可以进行三次操作的目标序列:
step1:swap(8,0):2 0 8 3
step2:swap(2,0):0 2 8 3
step3:swap(8,3):0 2 3 8
【数据规模】
30%的数据满足1≤n≤10^4;
100%的数据满足1≤n≤5*10^5。

-maxlong≤A[i] ≤maxlong;

T2:过路费

题目:

【问题描述】
有一天你来到了一个奇怪的国家,它有N个城市,城市之间有若干条双向道路连接,每条道路都有一定的费用,经过城市也要一定的费用。从一个城市到达另一个城市的总花费为路径上费用最大的城市费用(包括起点和终点)加上路径上所有的道路的费用。给出Q次询问,分别回答每次询问中两城市间的最少花费。保证城市之间可以互达。
【输入格式】
第一行两个整数N,M,表示有N个城市M条道路。
接下来N行每行一个整数,表示城市的费用ci。
接下来M行每行三个整数,x,y,z,表示城市x和城市y间有一条费用为z的道路。
接下来一行一个整数Q,表示询问次数。
接下来Q行每行两个整数x,y(x不等于y),表示询问从城市x到城市y的最小花费。
【输出格式】
共Q行每行一个整数,第i行的整数表示第i次询问的答案。
【样例输入】
3 3
1
3
2
1 2 1
2 3 1
1 3 3
2
1 3
1 3
【样例输出】
5
5
【数据规模】
对于30%的数据,N<=10,M<=20,Q<=5。
对于60%的数据,N<=200,M<=4000,Q<=100。
对于100%的数据,N<=300,M<=40000,Q<=100000,1<=ci<=100000,1<=z<=1000。

T3 上课

题目:

【问题描述】
学校里有许多节课,第i节课从ti时刻开始上,上课的时间为si,如果上了第i节课,你的做题能力将变成ci(是能力的数值,不是能力的增长值)。有N类作业,每类作业数量不限,每类作业完成一份所需要的时间为ai,做某类作业需要的做题能力达到qi(>=qi)才能完成。在每个时刻你可以选择上课、休息、做作业,如果选择上课则必须上完整节课,如果选择做作业必须花完整的ai时间做,同一时刻只能上一节课或做一份作业。而且人的精力有限,在T时刻后必须停止学习(部分课可能上到T时刻后)。求在时限内最多可以完成几份作业。在刚开始时,你的做题能力为1,时刻为1。
【输入格式】
第一行三个整数T,M,N,表示总时间,有M节课,有N类作业。
接下来M行每行三个整数ti,si,ci。
接下来N行每行两个整数ai,qi。
【输出格式】
共一行,一个整数ans,表示时限内最多可以完成几份作业。
【输入样例】
10 1 2
3 2 5
4 1
1 3
【输出样例】
6
【数据规模】
20%的数据满足M,N<=4,T<=15。
50%的数据满足M<=100,N<=1000,T<=1000。
100%的数据满足M<=1000,N<=100000,T<=100000,1<=ci<=100,1<=ai、ti<=T,1<=qi<=100。

T1解法:(水题)

核心程序:无

逆序对O(nlogn)归并排序。(具体做法参照其他博客)

T2解法:(做过,不水)

解法一:Floyd(n^3)N<=300
这题最主要的是要将city的位置排序,用sort的话得用一个很玄妙的make_pair或者用struct结构体,再存其排序后的位置与实际位置,存了后就Floyd跑一遍就可以了。(但是这也很玄学)

解法二:SPFA O(knm)较慢,大数据跑了0.6s
对于一个有两个条件的题目,我们可以从1到n分别枚举节点,使其为最大点,再SPFA找寻路径,加入到ans[][]里:

核心程序:

    (在SPFA中加入该代码)if(city[s]<city[to])continue;    (每次SPFA后进行该操作)    for(i=1;i<=n;i++){       for(j=1;j<=n;j++){          if(ans[i][j]>dis[i]+city[s]+dis[j]){         ans[i][j]=dis[i]+city[s]+dis[j];            }        }    }

T3解法:DP(看起来像”尼克松的任务”,但是却有不同)(比赛时看都没看)

易发现能力值都较小,因此我们可以以此突破
先将课程排序,再依次处理出能力值达到。。时的刷题速度,再动态规划一波。

核心程序:

    for(i=1;i<=m+1;i++){    for(j=0;j<i;j++){       dp[i]=Max(dp[i],dp[j]+(lesson[i].start-(lesson[j].start+lesson[j].last)+1)/mn[lesson[j].ability]);     }    }

贴标程

T2

#include<bits/stdc++.h>using namespace std;const int MAXN=40000+10;const long long inf=1e10;struct edge{    int to,w,last;}edges[MAXN<<1];int n,m,q,cnt,head[305];int city[305];long long ans[305][305];long long dis[305];bool vis[305];inline void read(int& x){    x=0;bool flag=false;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}    if(flag)x=-x;}inline void add(int u,int v,int w){    edges[++cnt].to=v;    edges[cnt].w=w;    edges[cnt].last=head[u];    head[u]=cnt;}void spfa(int s){    int i,j;    memset(vis,false,sizeof(vis));    memset(dis,0x3f,sizeof(dis));    queue<int>que;    que.push(s);vis[s]=true;dis[s]=0;    while(!que.empty()){        int x=que.front();que.pop();vis[x]=false;        for(i=head[x];i;i=edges[i].last){            int to=edges[i].to;            if(city[to]>city[s])continue;            if(dis[to]>dis[x]+edges[i].w){                dis[to]=dis[x]+edges[i].w;                if(!vis[to]){                    que.push(to);                    vis[to]=true;                }            }        }    }    for(i=1;i<=n;i++){        for(j=1;j<=n;j++){            if(ans[i][j]>dis[i]+city[s]+dis[j]){                ans[i][j]=dis[i]+city[s]+dis[j];            }        }    }}int main(){    int i,j;    read(n),read(m);    for(i=1;i<=n;i++)        read(city[i]);    for(i=1;i<=m;i++){        int a,b,x;        read(a),read(b),read(x);        add(a,b,x),add(b,a,x);    }    for(i=1;i<=n;i++){        for(j=1;j<=n;j++){            if(i!=j)ans[i][j]=inf;        }    }    for(i=1;i<=n;i++)    spfa(i);    read(q);    for(i=1;i<=q;i++){        int x,y;        read(x),read(y);        printf("%lld\n",ans[x][y]);    }    return 0;}

T3

#include<bits/stdc++.h>#define Min(a,b) (a)<(b)?(a):(b)#define Max(a,b) (a)>(b)?(a):(b)using namespace std;const int MAXM=1000+50,MAXN=100000+50;struct node1{    int start,last,ability;}lesson[MAXM];int t,m,n;int mn[110];int dp[MAXM];int cmp(node1 aa,node1 bb){    return aa.start<bb.start;    return aa.start==bb.start&&aa.last<bb.last;}int main(){    int i,j;//  freopen("a.in","r",stdin);//  freopen("a.out","w",stdout);    memset(mn,0x3f,sizeof (mn));    scanf("%d%d%d",&t,&m,&n);    lesson[0].ability=1,lesson[0].last=0,lesson[0].start=1;    for(i=1;i<=m;i++){        scanf("%d%d%d",&lesson[i].start,&lesson[i].last,&lesson[i].ability);    }    sort(lesson+1,lesson+m+1,cmp);    lesson[m+1].start=t+1;    for(i=1;i<=n;i++){        int x,y;        scanf("%d%d",&x,&y);        mn[y]=Min(mn[y],x);    }    for(i=1;i<=105;i++)mn[i]=Min(mn[i],mn[i-1]);//  for(i=1;i<=105;i++)printf("%d ",mn[i]);    for(i=1;i<=m+1;i++){        for(j=0;j<i;j++){            dp[i]=Max(dp[i],dp[j]+(lesson[i].start-(lesson[j].start+lesson[j].last))/mn[lesson[j].ability]);        }    }    printf("%d",dp[m+1]);    return 0;}
原创粉丝点击