noip2013
来源:互联网 发布:s7 200编程电缆 编辑:程序博客网 时间:2024/06/05 06:48
day1
t1
转圈游戏(circle)
裸地快速幂。。
#include<cstdio>using namespace std;int n,m,x,k;int fastpow(int a,int k){ int ans=1; while(k){ if(k&1) ans=(1ll*ans*a)%n; a=(1ll*a*a)%n; k>>=1; } return ans;}int main() { scanf("%d%d%d%d",&n,&m,&k,&x); printf("%d",(x+1ll*m*fastpow(10,k)%n)%n); return 0;}
t2
火柴排队
这个题可以贪心,最小价值一定是大小位置对应的,所以用下面的匹配上面的就行了
因为火柴棒数目有点大,需要离散化一下,因为火柴的长度不一。
然后可以对第一个串遍一个号,对应到第二个串里,就变成了两两交换排序问题
再一次转换为逆序对问题,就a了
#include<cstdio>#include<algorithm>using namespace std;#define ll long longconst int M=101001;const int P=99999997;struct st{ll f,s;};int n;st a[M];ll t[M],w[M],sum[M],ans,ff[M],tmp[M],tmp2[M];void add(ll x){ for(;x;x-=x&(-x)) sum[x]++;}ll ask(ll x){ ll tot=0; for(;x<=n;x+=x&(-x)) tot=(tot+sum[x])%P; return tot;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i].f),t[i]=a[i].f; for(int i=1;i<=n;i++) scanf("%lld",&a[i].s),w[i]=a[i].s; sort(t+1,t+n+1);sort(w+1,w+n+1); for(int i=1;i<=n;i++){ a[i].f=lower_bound(t+1,t+n+1,a[i].f)-t; a[i].s=lower_bound(w+1,w+n+1,a[i].s)-w; } for(int i=1;i<=n;i++) ff[a[i].f]=i; for(int i=1;i<=n;i++){ add(ff[a[i].s]); ans=(ans+ask(ff[a[i].s]+1))%P; } printf("%lld",ans%P); return 0;}
t3
货车运输
先找出最大生成森林,再找倍增找lca,找最小值
之前写了个tarjan错了。。。
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define ll long longconst int M=21000,INF=1e9+3;int fa[M],vis[M],tote,heade[M],nexe[M*2],toe[M*2],cose[M*2],tot,head[M],nex[M*2],to[M*2],cos[M*2],f[M],dep[M];int ff[M],zx[M],cnt,dx[M],dy[M],up[M][20],g[M][20];int n,m,q;struct st{ int x,y,z;}a[M]; bool cmp(const st a,const st b){ return a.z>b.z;}void add(int x,int y,int z){ nex[++tot]=head[x]; to[tot]=y; cos[tot]=z; head[x]=tot;}void adde(int x,int y){ nexe[++tote]=heade[x]; toe[tote]=y; heade[x]=tote;}int find(int x){ return f[x]==x?x:f[x]=find(f[x]);}void K(){ int j=1,num=n; while(j<=m) { int fx=find(a[j].x); int fy=find(a[j].y); if(fx==fy) { j++;continue; } f[fx]=fy; add(a[j].x,a[j].y,a[j].z); add(a[j].y,a[j].x,a[j].z); j++; num--; if(num==1) break; }}void dfs(int x){ vis[x]=1; for(int i=head[x];i;i=nex[i]){ int tmp=to[i]; if(!vis[tmp]){ up[tmp][0]=x; g[tmp][0]=cos[i]; dep[tmp]=dep[x]+1; dfs(tmp); } }} int lca(int x,int y) { if(x==y) return 0; int fx=find(x); int fy=find(y); if(fx!=fy) return -1; int minx=INF,miny=INF; if(dep[x]<dep[y]) swap(x,y); for(int i=18;i>=0;i--) { if(dep[up[x][i]]>=dep[y]&&up[x][i]) { minx=min(minx,g[x][i]); x=up[x][i]; } } if(x==y) return minx; for(int i=18;i>=0;i--) { if(up[x][i]!=up[y][i]) { minx=min(minx,g[x][i]); miny=min(miny,g[y][i]); x=up[x][i]; y=up[y][i]; } } minx=min(minx,g[x][0]); miny=min(miny,g[y][0]); return min(minx,miny);} int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); for(int i=1;i<=n;i++)f[i]=i; sort(a+1,a+m+1,cmp); K(); memset(g,127,sizeof g); scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&dx[i],&dy[i]); adde(dx[i],dy[i]); adde(dy[i],dx[i]); } for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); for(int j=1;(1<<j)<=n;j++) for(int i=1;i<=n;i++) if(up[up[i][j-1]][j-1]!=0){ up[i][j]=up[up[i][j-1]][j-1]; g[i][j]=min(g[i][j-1],g[up[i][j-1]][j-1]); } //for(int i=1;i<=2*q;i++) printf("%d ",lca[i]); for(int i=1;i<=q;i++){ if(find(dx[i])!=find(dy[i])) printf("-1\n");else printf("%d\n",lca(dx[i],dy[i])); }}
day2
t1
这个题正解是单调栈,因为山包你把它砍掉就行,只有上升可以增加高度,下降就可以直接去掉
这就是个单调栈,然后更新答案,用山顶减山脚
我是用了个优先队列+链表,也搞对了,我是每一次砍掉最高的山,然后把最高的山去掉,你可以看做和旁边的山合并成一个山了,这个可以用优先队列,然后记录个左右山的序号,用看得比较小的,更新答案,删山时用链表搞一下
#include<cstdio>#include<iostream>#include<queue>using namespace std;const int M=110000;struct st{ int x,t; inline int operator <(const st &a)const{ return a.x<x; }};int n,a[M];int cnt=1,f=1,h[M],minn[M];int ans,l[M],r[M];priority_queue < st > q;int t=0;int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); if(a[t]!=a[i]) { st tmp; tmp.x=-a[i]; tmp.t=i; q.push(tmp); l[i]=t,r[t]=i; t=i; } } while(!q.empty()){ st tmp=q.top(); //printf("%d ",-tmp.x); q.pop(); l[r[tmp.t]]=l[tmp.t]; r[l[tmp.t]]=r[tmp.t]; ans+=min(-tmp.x-a[l[tmp.t]],-tmp.x-a[r[tmp.t]]); } printf("%d",ans);}
t2
花匠
想一个问题,最后选的花一定是波浪线,一定包括所有峰(比左右都大得),所以结果就是峰的个数乘2
在特判一下两端是否是峰
#include<cstdio>#include<iostream>using namespace std;int n,a[1999999],tot;int s,f;int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { int x;scanf("%d",&x); if(a[tot]!=x) a[++tot]=x; } for(int i=1;i<=tot;i++) { if(a[i]>a[i-1]&&a[i]>a[i+1]) s++; } s=s*2; if(a[1]<a[2]) s++; if(a[tot]>a[tot-1]) s--; printf("%d",s);}
t3
华容道
阅读全文
1 0
- NOIP2013
- noip2013
- noip2013
- noip2013完挂
- [NOIP2013]花匠
- [NOIP2013]华容道
- NOIP2013华容道
- NOIP2013花匠
- NOIP2013 花匠
- NOIP2013华容道
- NOIP2013 花匠
- noip2013题解
- NOIP2013花匠
- NOIP2013 花匠
- NOIP2013 华容道
- NOIP2013 day2
- 【NOIP2013】花匠
- 【NOIP2013】day1
- Ionic 下拉刷新
- vs13+pcl1.8配置
- linux 命令安装 oracle jdk
- IFE-TASK32(任务三十二:表单(四)实现表单自动生成工厂)
- 微信支付放大招 再也不用担心限额了!
- noip2013
- 国内大公司的开源项目一览表(包含mysql读写分离等)
- http post payload request类型请求
- 使用HTML5里的classList操作CSS类的详细介绍
- C# 泛型使用
- pygdal-安装
- spring整合rabbitmq
- PHP实现邮件的自动发送
- 函数指针