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
- 5.21pkusc模拟赛6
- 5.21pkusc模拟赛5
- 5.16pkusc模拟赛1
- 5.16pkusc模拟赛2
- 5.17pkusc模拟赛3
- 5.17pkusc模拟赛4
- [关于thusc模拟(5.18)和pkusc模拟(5.19)]
- PKUSC 2017 酱油记
- PKUSC 2017 没约记
- PKUSC预热__被水题虐QoQ
- PKUSC前恢复性训练
- 2016.7.6 模拟赛
- 2014.9.6模拟赛【工资】
- 2014.10.6模拟赛【暗黑破坏神】
- 2014.10.6模拟赛【魔兽争霸】
- NOIP2017模拟赛(6) 总结
- 模拟赛
- 模拟赛~~
- Android Studio教程从入门到精通
- C++未使用\0可能出现乱码
- file!=null和file.exists()的区别
- LeetCode 148. Sort List(链表排序)
- snubber电路总结
- 5.21pkusc模拟赛6
- 知道这20个正则表达式,能让你少写1,000行代码
- Web缓存工作原理
- 【Spring】【笔记】《Spring In Action》第3章 简化XML配置
- Java基础回顾:覆写equals()方法
- SQL SERVER 查看进程冲突
- string、char*的区别和转换
- 使用Nginx负载均衡
- tomcat 日志统计分析