其他分享
首页 > 其他分享> > 6.30集训模拟赛4(炸裂的一天qwq)

6.30集训模拟赛4(炸裂的一天qwq)

作者:互联网

T1浇水:

  题目描述

  输入格式

  输出格式

  样例

  样例输入1

9 16 6
0 5
2 5
4 5
6 5
8 5
10 5
12 5
14 5
16 5

  样例输出1

 2

  样例输入2

8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4

  样例输出2

 6

  数据范围与提示

  分析:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int k,n,m;
int a,r;
int cnt;
struct wat{//记录一个点的左右最远的覆盖范围
    double L;//double!!!
    double R;
}w[N];

bool cmp(wat a,wat b){//按
    return a.L<b.L;
}

int main(){
    scanf("%d%d%d",&k,&n,&m);//输入
    for(int i=1;i<=k;i++){
        scanf("%d%d",&a,&r);
        if(r*2<=m)continue;//去除一些没用的喷水装置
        w[++cnt].L=a-sqrt(r*r-m*m/4.0);//等于也不行(喷一个线有啥用)
        w[cnt].R=a+sqrt(r*r-m*m/4.0);
    }
    sort(w+1,w+1+cnt,cmp);//排序
    double right=0;
    int ans=0;
    while(right<n){//
        ans++;
        double s=right;//用一个s保存right值因为后面的right值要变
        for(int i=1;i<=k&&w[i].L<=s;i++){
            if(right<w[i].R){
                right=w[i].R;//更新覆盖的最右边的值
            }
        }
        if(right==s&&s<n){//不满题意
            printf("-1\n");
            return 0;
        }
    }
    printf("%d\n",ans);
    return 0;
}

T2免费馅饼:

  题目描述:

  输入格式:

  输出格式:

  样例:

  样例输入:

3 3
0 1 2 5 
0 2 1 3
1 2 1 3
1 3 1 4

  样例输出:

12

  数据范围与提示:

  分析:

#include<bits/stdc++.h>
using namespace std;
const int N=2600;
int w,h;
int cnt;
int T,P,V,W,maxtime;
int t[N],p[N],v[N],val[N];
int f[N][N];
int hehe(int i,int j){
    int ans=0;
    for(int k=-2;k<=2;k++){
        if(j+k<0||j+k>w)continue;
        ans=max(ans,f[i+1][j+k]);
    }
    return ans;
}

int main(){    
    scanf("%d%d",&w,&h);
    h--;//注意减一
    while(scanf("%d%d%d%d",&T,&P,&V,&W)==4){
        if(h%V==0){
            t[++cnt]=T+h/V;//注意+T;
            p[cnt]=P;v[cnt]=V;val[cnt]=W;
            maxtime=max(maxtime,t[cnt]);//找出下落时间最大的值来
        }
    }
    if(cnt==0){//如果都不符合那就结束
        printf("0");
        return 0;
    }
    for(int i=1;i<=cnt;i++){//可能有不同时出发的但同时同地落下的馅饼。累加。
        f[t[i]][p[i]]+=val[i];
    }
    for(int i=maxtime-1;i>=0;i--){//从后往前
        for(int j=w;j>=0;j--){//maxtime注意减一因为转移有范围。
            f[i][j]+=hehe(i,j);
        }
    }
    printf("%d",f[0][(w+1)/2]);//f数组定义的是从i秒j地的最大分数
    return 0;
}

 


 

 T3压缩:dp(★★★★★★★★★★★★★★★★★★★★★★★★★......)

  呵呵,洛谷紫题,教练拿来当作入门题考,beng......

  题目描述:

   输入格式:

  输出格式:

  样例:

  样例输入1:

aaaaaaa

  样例输出1:

 5

  样例输入2:

bcdcdcdcdxcdcdcdcd

  样例输出2:

12

  数据范围与提示:

  50%的数据满足:1≤n≤20。

  100%的数据满足:1≤n≤50。

  分析:

 

#include <bits/stdc++.h>
using namespace std;
const int N=55;
char s[N];
int f[N][N][3];

bool judge(int l,int r){//判断前一半是否和后一半相等
    if((r-l+1)&1)return false;//长度为奇数
    int mid=(l+r)>>1;
    for(int i=l;i<=mid;i++)
        if(s[i]!=s[i+mid-l+1])return false;
    return true;
}


int main(){
    scanf("%s",s+1);
    int len = strlen(s+1);
    for(int i=1;i<=len;i++)//初始化为没有折叠
        for(int j=i;j<=len;j++)
            f[i][j][0]=f[i][j][1]=(j-i+1);
    for(int l=1;l<=len;l++){
        for(int i=1,j;(j=i+l)<=len;i++){//i为区间起点,j为区间终点
            if(judge(i,j))//区间[i,j]正好能折叠
                f[i][j][0]=min(f[i][(i+j)/2][0]+1,f[i][j][0]);
            for(int k=i;k<j;k++)//枚举区间的断点,有可能[i,k]能折叠
                f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k);    
            for(int k=i;k<j;k++)//枚举M的位置,即在k的后面加一个M
                f[i][j][1]=min(f[i][j][1],std::min(f[i][k][0],f[i][k][1])+min(f[k+1][j][0],f[k+1][j][1])+1);
        }
    }
    printf("%d\n",min(f[1][len][1],f[1][len][0]));
    return 0;
}

 

T4枪战Maf:(思维★★)

  题目描述:

  输入格式:

 

  输出格式:

 

  样例输出:

8
2 3 2 2 6 7 8 5

  样例格式:

3 5

  分析:

  设最大存活人数Max,最少存活人数Min 

 

#include<bits/stdc++.h>
using namespace std;
const int N=1000100;
int n;
int aim[N];
int Min,Max;
int q[N],rd[N];
bool die[N],live[N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&aim[i]);
        rd[aim[i]]++;//存入度
    }
    for(int i=1;i<=n;i++){
        if(rd[i]==0){
            Min++;//最小必活数+1
            Max++;//队列维护的是入度为0的点
            q[Max]=i;
        }
    }
    int aa=1;
    while(aa<=Max){//扫描队列
        int front=q[aa++];//取出队首并出队
        if(die[aim[front]])continue;//队首目标已死(多个入度为0的点指向一个点)
        die[aim[front]]=1;//队首目标必死
        int faim=aim[aim[front]];//队首目标的目标可死可不死,看决策
        rd[faim]--;
        live[faim]=1;//可以让他活,但想死的时候随时可以让他死,在环可以最后死
        if(rd[faim]==0){//虽然入度为0,但不一定是必活,所以Min不加
            q[++Max]=faim;
        }
    }//下面处理只剩下环
    for(int i=1;i<=n;i++){
        if(rd[i]&&!die[i]){
            int l=0,flag=0;//l记录环大小,flag标记环上是否有live的点 
            for(int j=i;!die[j];j=aim[j]){
                l++;
                flag|=live[j];
                die[j]=1;//标记已死,避免其他的再来计算
            }
            if(!flag&&l>1)Min++;//l=1表示自环,必死
            Max+=l/2;
        }
    }
    printf("%d %d",n-Max,n-Min);
    return 0;
}

 


 

 博主在没有任何编辑器的恶劣情况下成功夺得514高地(敲了一个多小时),点赞关注顶一下呗......@^_^@......

 

标签:装置,馅饼,炸裂,min,样例,6.30,int,喷水,qwq
来源: https://www.cnblogs.com/LightyaChoo/p/13215436.html