5.21pkusc模拟赛6

2 篇文章 0 订阅
2 篇文章 0 订阅

A.一直一个长度为n的序列,求对于相邻i,j,abs(a[i]-a[j])<=h的子数列个数%9901(n<=100000,h<=1000000000)(5.21)

首先离散化,然后考虑dp,dp[i]=sigma(dp[j]) (abs(dp[i]-dp[j])<=h) 然后上树状数组优化。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define N 100005
#define Mo 9901
#define ll long long
using namespace std;
int a[N],b[N],c[N],tmp[N],n,h;
ll ans[N];
int lowbit(int x){return x&-x;}
int binary_search1(int l,int r,int x){
    while(l<r){
        int mid=(l+r)>>1;
        if(b[mid]<x) l=mid+1;
        else r=mid;
    }
    return l;
}
int binary_search2(int l,int r,int x){
    while(l<r){
        int mid=(l+r)>>1;
        if(b[mid]<=x) l=mid+1;
        else r=mid;
    }
    return l-1;
}
void add(int pos,int x){
    while(pos<N){
        c[pos]+=x;
        pos+=lowbit(pos);
    }
}
ll getsum(int pos){
    ll ret=0;
    while(pos){
        ret+=c[pos];
        pos-=lowbit(pos);
    }
    return ret;
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    while(~scanf("%d%d",&n,&h)){
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        memset(tmp,0,sizeof(tmp));
        memset(ans,0,sizeof(ans));
        int cnt=0;
        ll res=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]),tmp[i]=a[i];
        sort(tmp+1,tmp+1+n);
        for(int i=1;i<=n;i++)
            if(tmp[i]!=tmp[i-1])
                b[++cnt]=tmp[i];
        //for(int i=1;i<=n;i++) printf("%d ",b[i]);puts("");
        for(int i=1;i<=n;i++){
            int x=binary_search1(1,cnt+1,max(a[i]-h,0));
            int y=binary_search2(1,cnt+1,a[i]+h);
            int now=binary_search2(1,cnt+1,a[i]);
            //printf("%d %d %d\n",x,y,now);
            ans[i]+=getsum(y)-getsum(x-1);
            ans[i]%=Mo;
            //printf("*%d\n",ans[i]);
            add(now,ans[i]+1);
            res+=ans[i];res%=Mo;
        }
        printf("%lld\n",res);
    }
    return 0;
}

B.求次短路。

正反两次求最短路,每局每条边,设当前枚举边为(u,v,w),则ans=min(ans,dis1[u]+w+dis2[v]) (dis1[u]+w+dis2[v]!=dis1[n])(5.21)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define inf 0x7fffffff
#define N 100005
using namespace std;
struct E {int to,nxt,w;}edge[N*2];
int n,r,tot=1;
int dis[2][N],u[N],v[N],w[N],idx[N];
bool vis[N];
queue<int>q;
void addedge(int from,int to,int w){
    edge[tot].to=to;edge[tot].w=w;edge[tot].nxt=idx[from];idx[from]=tot++;
}
void spfa(int s,int t,int o){
    memset(dis[o],127,sizeof(dis[o]));
    memset(vis,0,sizeof(vis));
    dis[o][s]=0;vis[s]=0;q.push(s);
    while(!q.empty()){
        int x=q.front();q.pop();vis[x]=0;
        for(int t=idx[x];t;t=edge[t].nxt){
            E e=edge[t];
            if(dis[o][x]+e.w<dis[o][e.to]){
                dis[o][e.to]=dis[o][x]+e.w;
                if(!vis[e.to]) q.push(e.to),vis[e.to]=1;
            }
        }
    }
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    scanf("%d%d",&n,&r);
    int x,y,ww;
    for(int i=1;i<=r;i++)
        scanf("%d%d%d",&x,&y,&ww),addedge(x,y,ww),addedge(y,x,ww),u[i]=x,v[i]=y,w[i]=ww;
    spfa(1,n,0);
    spfa(n,1,1);
    int ans=inf;
    for(int i=1;i<=r;i++){
        int x=u[i],y=v[i],ww=w[i];
        if(dis[0][x]+dis[1][y]+ww!=dis[0][n]) 
            ans=min(ans,dis[0][x]+dis[1][y]+ww);
        x=v[i];y=u[i];
        if(dis[0][x]+dis[1][y]+ww!=dis[0][n]) 
            ans=min(ans,dis[0][x]+dis[1][y]+ww);
    }
    printf("%d\n",ans);
    return 0;
}

C.静态区间第k小。(5.23)

听说有种划分树。。写的主席树。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#define N 100005
using namespace std;
map<int,int>mp;
struct seg{
    int ls,rs,l,r,num;
}t[2400000];// 4*N + NlogN
int root[N],a[N],b[N];
int n,m,cnt;
void init_build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    if(l==r) return;
    int ls=++cnt,rs=++cnt;
    t[k].ls=ls;t[k].rs=rs;
    int mid=(l+r)>>1;
    init_build(ls,l,mid);
    init_build(rs,mid+1,r);
}
void modify(int k,int x){
    int l=t[k].l,r=t[k].r;
    int mid=(l+r)>>1;
    if(l==r) {t[k].num++;return;} 
    if(x<=mid){
        t[k].num++;
        t[++cnt]=t[t[k].ls];
        t[k].ls=cnt;
        if(t[k].ls) modify(t[k].ls,x);
    }
    if(x>=mid+1){
        t[k].num++;
        t[++cnt]=t[t[k].rs];
        t[k].rs=cnt;
        if(t[k].rs) modify(t[k].rs,x);
    }
}
void query(int a,int b,int k,int &ret){
    int lsa=t[a].ls,lsb=t[b].ls;
    int rsa=t[a].rs,rsb=t[b].rs;
    if(t[a].l==t[a].r) {ret=t[a].l;return;}
    if(t[lsb].num-t[lsa].num>=k)
        query(lsa,lsb,k,ret);
    else query(rsa,rsb,k-(t[lsb].num-t[lsa].num),ret);
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+1+n);cnt=0;
    for(int i=1;i<=n;i++)
        if(!mp.count(b[i])){
            mp[b[i]]=++cnt;
            b[cnt]=b[i];
        }
    cnt=1;root[0]=1;
    init_build(1,1,mp[b[n]]);
    //for(int i=1;i<=20;i++) printf("%d %d %d %d %d %d\n",i,t[i].l,t[i].r,t[i].ls,t[i].rs,t[i].num);
    for(int i=1;i<=n;i++){
        root[i]=++cnt;
        t[root[i]]=t[root[i-1]];
        modify(root[i],mp[a[i]]);
    }
    for(int i=1;i<=m;i++){
        int l,r,k,ret;
        scanf("%d%d%d",&l,&r,&k);
        query(root[l-1],root[r],k,ret);
        printf("%d\n",b[ret]);
    }
    //for(int i=1;i<=35;i++) printf("%d %d %d %d %d %d\n",i,t[i].l,t[i].r,t[i].ls,t[i].rs,t[i].num);
    return 0;
}

D.长度为20的01序列,可以对一个数进行一次操作,操作是这个数及其相邻的数字取反。问这个01序列变成全0序列。保证有解。(5.21)

000101……1左边的0一定要翻,所以就每局从左还是从右翻……

#include<iostream>
#include<cstdio>
using namespace std;
int a[21],b[21],ans1,ans2;
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    for(int i=1;i<=20;i++) scanf("%d",&a[i]),b[i]=a[i];
    for(int i=1;i<=18;i++){
        if(a[i]==0) continue;
        a[i]^=1;a[i+1]^=1;a[i+2]^=1;
        ans1++;
    }if(a[19]+a[20]==2) ans1++;
    for(int i=20;i>=3;i--){
        if(b[i]==0) continue;
        b[i]^=1;b[i-1]^=1;b[i-2]^=1;
        ans2++;
    }if(b[1]+b[2]==2) ans2++;
    printf("%d\n",min(ans1,ans2));
    return 0;
}

F.在m*n的地图上有一些障碍,求使已知三点连通的最小路径长度。(m,n<=100)(5.21)

最小的路径长度一定是三条路交于一个点,枚举这个点即可。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define N 105
#define inf 1<<30
using namespace std;
struct node{int x,y;};
int dirx[5]={0,1,-1,0,0};
int diry[5]={0,0,0,-1,1};
int dis[4][N][N];
bool vis[N][N];
char map[N][N];
int n,m;
queue<node>q;
void bfs(int x,int y,int o){
    q.push((node){x,y});
    dis[o][x][y]=0;
    vis[x][y]=1;
    while(!q.empty()){
        node now=q.front();q.pop();
        for(int i=1;i<=4;i++){
            int nx=now.x+dirx[i];
            int ny=now.y+diry[i];
            if(nx&&nx<=n&&ny&&ny<=m&&map[nx][ny]!='X'&&!vis[nx][ny]){
                q.push((node){nx,ny});
                vis[nx][ny]=1;
                dis[o][nx][ny]=dis[o][now.x][now.y]+1;
            }
        }
    }
}
int main(){
//  freopen("in.txt","r",stdin);
//  freopen("out.txt","w",stdout);
    while(~scanf("%d%d",&n,&m)){
        int x[4],y[4],cnt=0;
        memset(dis,255,sizeof(dis));
        for(int i=1;i<=n;i++){
            scanf("%s",map[i]+1);
            for(int j=1;j<=m;j++)
                if(map[i][j]=='F'||map[i][j]=='J'||map[i][j]=='Q')
                    x[++cnt]=i,y[cnt]=j;
        }
        //for(int i=1;i<=cnt;i++) printf("%d %d\n",x[i],y[i]);
        for(int i=1;i<=3;i++){
            memset(vis,0,sizeof(vis));
            bfs(x[i],y[i],i);
        }
        int res=inf;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                bool flag=0;int ans=0;
                for(int k=1;k<=3;k++){
                    if(dis[k][i][j]==-1) {flag=1;break;}
                    ans+=dis[k][i][j];
                }
                if(!flag) res=min(res,ans-2);
            }
        if(res==inf) printf("Impossible\n");
        else printf("%d\n",res);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值