5.21pkusc模拟赛6

来源:互联网 发布:最新淘宝助理官方下载 编辑:程序博客网 时间:2024/06/07 02:49

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 longusing 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 100005using 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 100005using namespace std;map<int,int>mp;struct seg{    int ls,rs,l,r,num;}t[2400000];// 4*N + NlogNint 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<<30using 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
原创粉丝点击