zoukankan      html  css  js  c++  java
  • 2019/2/21测试(noip2015提高组day2

    出乎意料的一次考试,第一题二分的左界初始化错了,本来是找两个石头间的最短距离然而只有50分,最后改成0就过了,心痛。。。

    跳石头

    题目背景

    一年一度的“跳石头”比赛又要开始了!

    题目描述

    这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NNN 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

    为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 MMM 块岩石(不能移走起点和终点的岩石)。

    输入输出格式

    输入格式:

    第一行包含三个整数 L,N,ML,N,ML,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证 L≥1L geq 1L1 且 N≥M≥0N geq M geq 0NM0。

    接下来 NNN 行,每行一个整数,第 iii 行的整数 Di(0<Di<L)D_i( 0 < D_i < L)Di(0<Di<L), 表示第 iii 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

    输出格式:

    一个整数,即最短跳跃距离的最大值。

    输入输出样例

    输入样例#1: 复制
    25 5 2 
    2
    11
    14
    17 
    21
    输出样例#1: 复制
    4

    说明

    输入输出样例 1 说明:将与起点距离为 222和 141414 的两个岩石移走后,最短的跳跃距离为 444(从与起点距离 171717 的岩石跳到距离 212121 的岩石,或者从距离 212121 的岩石跳到终点)。

    另:对于 20%20\%20%的数据,0≤M≤N≤100 ≤ M ≤ N ≤ 100MN10。

    对于50%50\%50%的数据,0≤M≤N≤1000 ≤ M ≤ N ≤ 1000MN100。

    对于 100%100\%100%的数据,0≤M≤N≤50,000,1≤L≤1,000,000,0000 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,0000MN50,000,1L1,000,000,000。

     1 // luogu-judger-enable-o2
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=50100;
     5 int a[maxn],l,n,m;
     6 
     7 bool pd(int x)
     8 {
     9     int zb=0,tot=0;
    10     for(int i=1;i<=n;i++)
    11     {
    12         if(a[i]-zb>=x) zb=a[i];
    13         else tot++;
    14     }
    15     return tot<=m;
    16 }
    17 
    18 int main()
    19 {
    20     //freopen("input.txt","r",stdin);
    21     int left=0,right=0;
    22     scanf("%d%d%d",&l,&n,&m);
    23     for(int i=1;i<=n;i++) 
    24     {
    25         scanf("%d",&a[i]);
    26     }
    27     right=l;
    28     while(left<=right)
    29     {
    30         int mid=(left+right)>>1;
    31         if(!pd(mid)) right=mid-1;
    32         else left=mid+1;
    33     }
    34     printf("%d",left-1);
    35     return 0;
    36  } 
    View Code

    二分答案再判断,挺水的一题。。

    子串

    题目描述

    有两个仅包含小写英文字母的字符串 AAA 和 BBB。

    现在要从字符串 AAA 中取出 kkk 个互不重叠的非空子串,然后把这 kkk 个子串按照其在字符串 AAA 中出现的顺序依次连接起来得到一个新的字符串。请问有多少种方案可以使得这个新串与字符串 BBB 相等?

    注意:子串取出的位置不同也认为是不同的方案。

    输入输出格式

    输入格式:

    第一行是三个正整数 n,m,kn,m,kn,m,k,分别表示字符串 AAA 的长度,字符串 BBB 的长度,以及问题描述中所提到的 kkk,每两个整数之间用一个空格隔开。

    第二行包含一个长度为 nnn 的字符串,表示字符串 AAA。

    第三行包含一个长度为 mmm 的字符串,表示字符串 BBB。

    输出格式:

    一个整数,表示所求方案数。

    由于答案可能很大,所以这里要求输出答案对 100000000710000000071000000007 取模的结果。

    输入输出样例

    输入样例#1: 复制
    6 3 1 
    aabaab 
    aab
    输出样例#1: 复制
    2
    输入样例#2: 复制
    6 3 2 
    aabaab 
    aab
    输出样例#2: 复制
    7
    输入样例#3: 复制
    6 3 3 
    aabaab 
    aab
    输出样例#3: 复制
    7

    说明

    对于第 1 组数据:1≤n≤500,1≤m≤50,k=11≤n≤500,1≤m≤50,k=11n500,1m50,k=1;
    对于第 2 组至第 3 组数据:1≤n≤500,1≤m≤50,k=21≤n≤500,1≤m≤50,k=21n500,1m50,k=2;
    对于第 4 组至第 5 组数据:1≤n≤500,1≤m≤50,k=m1≤n≤500,1≤m≤50,k=m1n500,1m50,k=m;
    对于第 1 组至第 7 组数据:1≤n≤500,1≤m≤50,1≤k≤m1≤n≤500,1≤m≤50,1≤k≤m1n500,1m50,1km;
    对于第 1 组至第 9 组数据:1≤n≤1000,1≤m≤100,1≤k≤m1≤n≤1000,1≤m≤100,1≤k≤m1n1000,1m100,1km;
    对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m1≤n≤1000,1≤m≤200,1≤k≤m1n1000,1m200,1km。

    dp题但当时没想出如何表示状态

    后来讲了后才豁然开朗。。

    用dp[i][j][k][0/1] 表示a选到第i个,b选到第j个,正在选第k个字串,0表示当前不选,1表示要选,因为4微要炸,把第一维进行滚动;转移的话意会下就好了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e3+5;
     4 const int mod=1000000007;
     5 int n,m,k,dp[2][maxn][maxn][2];
     6 
     7 char a[maxn],b[maxn];
     8 
     9 int main(){
    10     scanf("%d%d%d",&n,&m,&k);
    11     scanf("%s%s",a+1,b+1);
    12     dp[0][0][0][0]=dp[1][0][0][0]=1;
    13     for(int i=1;i<=n;i++) 
    14         for(int j=1;j<=m;j++)
    15             for(int p=1;p<=k;p++){
    16                     dp[i%2][j][p][0] = (dp[(i-1)%2][j][p][0] + dp[(i-1)%2][j][p][1]) % mod;
    17                     if(a[i]==b[j]) dp[i%2][j][p][1] = ((dp[(i-1)%2][j-1][p][1] + dp[(i-1)%2][j-1][p-1][0]) % mod + dp[(i-1)%2][j-1][p-1][1]) % mod;//注意要摸两次,只摸一次我只有60分(洛谷测的
    18                 else dp[i%2][j][p][1]=0;
    19             }
    20     printf("%d",(dp[n%2][m][k][1]+dp[n%2][m][k][0])%mod);
    21     return 0;
    22 }
    View Code

    运输计划

    题目背景

    公元 204420442044 年,人类进入了宇宙纪元。

    题目描述

    公元204420442044 年,人类进入了宇宙纪元。

    L 国有 nnn 个星球,还有 n−1n-1n1 条双向航道,每条航道建立在两个星球之间,这 n−1n-1n1 条航道连通了 LLL 国的所有星球。

    小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 uiu_iui 号星球沿最快的宇航路径飞行到 viv_ivi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 jjj,任意飞船驶过它所花费的时间为 tjt_jtj,并且任意两艘飞船之间不会产生任何干扰。

    为了鼓励科技创新, LLL 国国王同意小 PPP 的物流公司参与 LLL 国的航道建设,即允许小PPP 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

    在虫洞的建设完成前小 P 的物流公司就预接了 mmm 个运输计划。在虫洞建设完成后,这 mmm 个运输计划会同时开始,所有飞船一起出发。当这 mmm 个运输计划都完成时,小 PPP 的物流公司的阶段性工作就完成了。

    如果小 PPP 可以自由选择将哪一条航道改造成虫洞, 试求出小 PPP 的物流公司完成阶段性工作所需要的最短时间是多少?

    输入输出格式

    输入格式:

    第一行包括两个正整数 n,mn, mn,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 111 到 nnn 编号。

    接下来 n−1n-1n1 行描述航道的建设情况,其中第 iii 行包含三个整数 ai,bia_i, b_iai,bitit_iti,表示第 iii 条双向航道修建在 aia_iaibib_ibi 两个星球之间,任意飞船驶过它所花费的时间为 tit_iti。数据保证 1≤ai,bi≤n1 leq a_i,b_i leq n1ai,bin 且 0≤ti≤10000 leq t_i leq 10000ti1000。

    接下来 mmm 行描述运输计划的情况,其中第 jjj 行包含两个正整数 uju_jujvjv_jvj,表示第 jjj 个运输计划是从 uju_juj 号星球飞往 vjv_jvj号星球。数据保证 1≤ui,vi≤n1 leq u_i,v_i leq n1ui,vin

    输出格式:

    一个整数,表示小 PPP 的物流公司完成阶段性工作所需要的最短时间。

    输入输出样例

    输入样例#1: 复制
    6 3 
    1 2 3 
    1 6 4 
    3 1 7 
    4 3 6 
    3 5 5 
    3 6 
    2 5 
    4 5
    输出样例#1: 复制
    11

    说明

    所有测试数据的范围和特点如下表所示

    请注意常数因子带来的程序效率上的影响。

    正正经经的一个压轴题,但一些知识到位了还是能做

    1.lca用来找距离,并维护一些标记,我用的倍增

    2.树上差分,与lca一起用,在起始点与终点处加一,lca处减二(因为是边的差分

    3.外层套个二分,枚举答案进行判断。大功告成

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 3e5+10;
     4 inline int read(){
     5     int x=0,f=1;char ch=getchar();
     6     while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
     7     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
     8     return f*x;
     9 }
    10 
    11 int dp[maxn][26],maxd,head[maxn],size=0,deep[maxn],dis[maxn],id[maxn],cnt=0,k,tmp[maxn],n,m;
    12 
    13 struct node{
    14     int u,v,lcaa,diss;
    15 }lu[maxn];
    16 
    17 struct edge{
    18     int v,nex,w;
    19 }e[maxn<<1];
    20 
    21 void adde(int u,int v,int w){e[size].v=v;e[size].w=w;e[size].nex=head[u];head[u]=size++;}
    22 
    23 void dfs(int u){
    24     if(dp[u][0]!=-1) maxd=max(maxd,deep[u]=deep[dp[u][0]]+1);
    25     id[++cnt]=u;
    26     for(int i=head[u];~i;i=e[i].nex){
    27         int v=e[i].v;
    28         if(dp[u][0]==v) continue;
    29         dis[v]=dis[u]+e[i].w;
    30         dp[v][0]=u;
    31         dfs(v);
    32     }
    33 }
    34 
    35 void doubling(){
    36     for(int j=1;j<=k;j++)
    37         for(int i=1;i<=n;i++)
    38         if(dp[i][j-1]!=-1) dp[i][j]=dp[dp[i][j-1]][j-1];
    39 }
    40 
    41 int lca(int x,int y){
    42     if(deep[x]<deep[y]) swap(x,y);
    43     for(int i=k;i>=0;i--)
    44     if(dp[x][i]!=-1&&deep[dp[x][i]]>=deep[y]) x=dp[x][i];
    45     if(x==y) return x;
    46     for(int i=k;i>=0;i--)
    47         if(dp[x][i]!=dp[y][i]) {
    48             x=dp[x][i],y=dp[y][i];
    49         }
    50     return dp[x][0];
    51 }
    52 
    53 bool check(int mid){
    54     int ans=0,tot=0;
    55     memset(tmp,0,sizeof(tmp));
    56     for(int i=1;i<=m;i++){
    57         if(lu[i].diss>mid) tmp[lu[i].u]++,tmp[lu[i].v]++,tmp[lu[i].lcaa]-=2,ans=max(ans,lu[i].diss-mid),tot++;
    58     }
    59     if(tot==0) return 1;
    60     for(int i=n;i>=1;i--) tmp[dp[id[i]][0]]+=tmp[id[i]];
    61     for(int i=2;i<=n;i++) if(tmp[i]==tot&&dis[i]-dis[dp[i][0]]>=ans) return 1;
    62     return 0;
    63 }
    64 
    65 int main(){
    66     int l=0,r=0;
    67     n=read(),m=read();
    68     memset(head,-1,sizeof(head));memset(dp,-1,sizeof(dp));
    69     for(int i=1;i<n;i++){
    70         int u=read(),v=read(),w=read();adde(u,v,w);adde(v,u,w);r+=w;
    71     }
    72     dfs(1);
    73     k=(int) (log(maxd)/log(2));
    74     doubling();
    75     for(int i=1;i<=m;i++){
    76         int u=read(),v=read();
    77         lu[i].u=u,lu[i].v=v;
    78         lu[i].lcaa=lca(u,v);
    79         lu[i].diss=dis[u]+dis[v]-2*dis[lu[i].lcaa];
    80     }
    81     int ans=0;
    82     while(l<=r){
    83         int mid=(l+r)>>1;
    84         if(check(mid)) r=mid-1,ans=mid;
    85         else l=mid+1;
    86     }
    87     printf("%d",ans);
    88 }
    View Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e3+5;
     4 const int mod=1000000007;
     5 int n,m,k,dp[2][maxn][maxn][2];
     6 
     7 char a[maxn],b[maxn];
     8 
     9 int main(){
    10     scanf("%d%d%d",&n,&m,&k);
    11     scanf("%s%s",a+1,b+1);
    12     dp[0][0][0][0]=dp[1][0][0][0]=1;
    13     for(int i=1;i<=n;i++) 
    14         for(int j=1;j<=m;j++)
    15             for(int p=1;p<=k;p++){
    16                     dp[i%2][j][p][0] = (dp[(i-1)%2][j][p][0] + dp[(i-1)%2][j][p][1]) % mod;
    17                     if(a[i]==b[j]) dp[i%2][j][p][1] = ((dp[(i-1)%2][j-1][p][1] + dp[(i-1)%2][j-1][p-1][0]) % mod + dp[(i-1)%2][j-1][p-1][1]) % mod;
    18                 else dp[i%2][j][p][1]=0;
    19             }
    20     printf("%d",(dp[n%2][m][k][1]+dp[n%2][
  • 相关阅读:
    jdbc连接Sql server数据库,并查询数据
    HttpClient,post请求,发送json,并接收数据
    SQL SERVER存储过程一
    HttpClient,get请求,发送并接收数据
    工作中操作数据库实例
    存储过程的实例(公司)
    eclipse发布项目后,项目所在的位置
    SQLSERVER存储过程基本语法
    SAXReader解析
    导包
  • 原文地址:https://www.cnblogs.com/plysc/p/10412743.html
Copyright © 2011-2022 走看看