tags:

  • 模拟
  • 快速幂
  • 逆序对
  • 树状数组
  • 归并排序
  • 最小生成树
  • lca
  • 倍增

    categories:
  • 信息学竞赛
  • 总结

tex live 2017.iso

转圈游戏

火柴排队

货车运输

转圈游戏

solution

  就是要求让一个人在一个圈上走一定步数, 问最后在哪里.例如走\(10^k\)次, 一次走\(\text{m}\)步, 初始时在\(\text{x}\), 圈长\(\text{n}\), 那么它最后的位置就是:

\[x+m10^k\mod n
\]

那么直接用快速幂暴力求出这个式子的值.

code

  1. #include<cstdio>
  2. int n,m,k,x;
  3. long long pow(int a,int b){
  4. long long ans=1ll,bas=a;
  5. while(b){
  6. if(b&1)ans*=bas;
  7. ans%=n;
  8. if(!bas)return ans;
  9. bas*=bas;bas%=n;
  10. if(!bas)return false;
  11. b>>=1;
  12. }
  13. return ans;
  14. }
  15. int main(){
  16. scanf("%d%d%d%d",&n,&m,&k,&x);
  17. long long ans=x,mm=pow(10,k);
  18. ans+=m*mm%n;
  19. ans%=n;
  20. printf("%lld\n",ans);
  21. return 0;
  22. }

火柴排队

solution

  其实就是将其中一个通过交换两个相邻的元素使得变化后的序列与另一个序列最相近, 问操作次数.

  其实就是使得两个序列中最大的元素位置相同, 第二大的元素位置也相同, 第三大的元素位置相同......那么元素的具体大小其实根本无所谓, 只需要知道元素之间的大小关系, 所以可以先将两个序列离散化, 然后找到其中一个的元素在另一个中的位置, 记为序列\(\text{c}\), 经离散后的序列记为\(\text{a,b}\), 那么我们进行的交换操作, 实际上就是将\(\text{c}\)变为序列\(1,2,\cdots ,n\), 这样其实就是将\(\text{b}\)变成\(\text{a}\).

Code

  1. #include<algorithm>
  2. #include<cstdio>
  3. #define N 100005
  4. #define mod 99999997
  5. int ans;
  6. int n,u[N];
  7. int a[N],b[N];
  8. int e[N],f[N],g[N];
  9. void mergesort(int l,int r){
  10. if(l==r)return;
  11. int mid,i,j,k;
  12. mid=(l+r)>>1;
  13. mergesort(l,mid);
  14. mergesort(mid+1,r);
  15. i=l,j=mid+1,k=l;
  16. while(i<=mid&j<=r)
  17. if(g[i]>=g[j])u[k++]=g[j++],ans+=(mid-i+1)%mod,ans%=mod;
  18. else u[k++]=g[i++];
  19. while(i<=mid)u[k++]=g[i++];
  20. while(j<=r)u[k++]=g[j++];
  21. for(i=l;i<=r;i++)g[i]=u[i];
  22. }
  23. struct Node{
  24. int val,pos;
  25. bool operator<(const Node& s)const{
  26. return val<s.val;
  27. }
  28. }c[N],d[N];
  29. int main(){
  30. scanf("%d",&n);
  31. for(int i=1;i<=n;++i)scanf("%d",&a[i]);
  32. for(int i=1;i<=n;++i)scanf("%d",&b[i]);
  33. for(int i=1;i<=n;++i)c[i]=(Node){a[i],i};
  34. for(int i=1;i<=n;++i)d[i]=(Node){b[i],i};
  35. std::sort(c+1,c+n+1);std::sort(d+1,d+n+1);
  36. for(int i=1;i<=n;++i)e[c[i].pos]=i;
  37. for(int i=1;i<=n;++i)f[d[i].pos]=i;
  38. for(int i=1;i<=n;++i)g[i]=c[f[i]].pos;
  39. mergesort(1,n);
  40. printf("%d",ans);
  41. return 0;
  42. }

货车运输

  这个经典的题目不知道做了多少遍了, 这次做还是发现了一些问题.

Solution

  需要使得图上两点之间经过路径上边的最小值最大, 首先将原图变成最大生成树, 因为两点之间经过的最小边权最大的路径必然存在在最大生成树上. 记两点之间的路径的转折点为\(\text{lca}\)(最近公共祖先),在最大生成树上两点\(\text{u,v}\)之间路径上边的最小值就是\(\text{u}\)到\(\text{lca}\)路径上边的最小值或者是\(\text{u}\)到\(\text{lca}\)路径上边的最小值.

  • 需要用倍增来加速\(\text{lca}\)的求解, 也可以用树链剖分, 用\(f(u,i)\)表示从\(\text{u}\)向上第\(2^i\)个点是哪个点.递推公式为:

\[f(u,i)=f(f(u,i-1),i-1)
\]

  • 求\(树上两点之间路径的最小值\)可以使用\(\text{RMQ}\)算法, 用\(d(u,i)\)表示从$\text{u}以上\(2^i\)个点路径的最小值, 那么递推公式为:

\[d(u,i)=\max{d(u,i-1),d(f(u,i-1),i-1)}
\]

  \(f(u,0)\)和\(d(u,0)\)可以在dfs中直接得到, \(f(u,i)\)和\(d(u,i)\)需要递推来获得.

Code

  1. #include<algorithm>
  2. #include<cstdio>
  3. #define N 500005
  4. #define inf 0x3f3f3f3f
  5. int n,m,q;
  6. int fa[N];
  7. int dep[N];
  8. int f[N][20];
  9. int d[N][20];
  10. int min(int i,int j){
  11. return i>j?j:i;
  12. }
  13. int find(int s){
  14. if(fa[s]!=s)fa[s]=find(fa[s]);
  15. return fa[s];
  16. }
  17. struct E{
  18. int u,v,cost;
  19. void Init(){
  20. scanf("%d%d%d",&u,&v,&cost);
  21. }
  22. bool operator<(const E&s)const{
  23. return cost>s.cost;
  24. }
  25. void print(){
  26. printf("%d %d %d\n",u,v,cost);
  27. }
  28. }edge[N];
  29. int head[N],tot;
  30. struct Edge{
  31. int v,c,nxt;
  32. }e[N];
  33. void AddEdge(int u,int v,int c){
  34. e[++tot]=(Edge){v,c,head[u]};head[u]=tot;
  35. e[++tot]=(Edge){u,c,head[v]};head[v]=tot;
  36. }
  37. void dfs(int x,int fath){
  38. f[x][0]=fath;dep[x]=dep[fath]+1;
  39. for(int i=head[x];i;i=e[i].nxt){
  40. if(e[i].v==fath)continue;
  41. d[e[i].v][0]=e[i].c;dfs(e[i].v,x);
  42. }
  43. }
  44. int Lca(int u,int v){
  45. int cha;
  46. if(dep[u]<dep[v])std::swap(u,v);
  47. for(int i=19;i>-1;--i)
  48. if(dep[f[u][i]]>=dep[v])
  49. u=f[u][i];
  50. for(int i=19;i>-1;--i)
  51. if(f[u][i]!=f[v][i])
  52. u=f[u][i],v=f[v][i];
  53. if(u!=v)return f[u][0];
  54. return u;
  55. }
  56. int Ans(int u,int v){
  57. if(u==v)return inf;
  58. int ans=inf;
  59. for(int i=19;i>-1;--i)
  60. if(dep[f[u][i]]>=dep[v])
  61. ans=min(d[u][i],ans),u=f[u][i];
  62. return ans;
  63. }
  64. int main(){
  65. scanf("%d%d",&n,&m);
  66. for(int i=1;i<=m;++i)edge[i].Init();
  67. for(int i=1;i<=n;++i)fa[i]=i;
  68. std::sort(edge+1,edge+m+1);int f1,f2,flag=0;
  69. for(int pos=1,f1,f2,i=1;i<n;++i){
  70. for(f1=find(edge[pos].u),f2=find(edge[pos].v);f1==f2;++pos,f1=find(edge[pos].u),f2=find(edge[pos].v))
  71. if(pos>m){flag=1;break;}
  72. if(flag)break;
  73. fa[f1]=f2;
  74. AddEdge(edge[pos].u,edge[pos].v,edge[pos].cost);
  75. //edge[pos].print();
  76. }
  77. dfs(1,0);
  78. for(int i=1;i<20;++i)
  79. for(int j=1;j<=n;++j)
  80. f[j][i]=f[f[j][i-1]][i-1];
  81. for(int i=1;i<20;++i)
  82. for(int j=1;j<=n;++j)
  83. d[j][i]=min(d[j][i-1],d[f[j][i-1]][i-1]);
  84. scanf("%d",&q);
  85. int u,v,lca;
  86. while(q--){
  87. scanf("%d%d",&u,&v);
  88. lca=Lca(u,v);
  89. if(find(u)!=find(v))printf("-1\n");
  90. else printf("%d\n",min(Ans(u,lca),Ans(v,lca)));
  91. }
  92. return 0;
  93. }

NOIP 2013 day1的更多相关文章

  1. NOIP 2013 货车运输【Kruskal + 树链剖分 + 线段树 】【倍增】

    NOIP 2013 货车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在 ...

  2. Luogu 1979 NOIP 2013 华容道(搜索,最短路径)

    Luogu 1979 NOIP 2013 华容道(搜索,最短路径) Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面 ...

  3. [Noip 2013 Day1-3] 货车运输 做法总结

    [Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...

  4. luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers

    目录 luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers 简述题意: Solution: Code luoguP6754 [BalticOI ...

  5. P6753 [BalticOI 2013 Day1] Ball Machine

    P6753 [BalticOI 2013 Day1] Ball Machine 题意 给你一个树,每次从根节点放一个求,如果其子节点有空这个球会向下滚,若有多个节点为空则找儿子中以子树内编号的最小值为 ...

  6. NOIP 2013 提高组 day1 T2 火柴排队 归并 逆序对

    描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑i=1n(ai−bi)2∑i=1n(ai−bi) ...

  7. noip 2013 提高组 day1

    1.转圈游戏: 解析部分略,快速幂就可以过 Code: #include<iostream> #include<fstream> using namespace std; if ...

  8. 【CodeVS 3290】【NOIP 2013】华容道

    http://codevs.cn/problem/3290/ 据说2013年的noip非常难,但Purpleslz学长还是AK了.能A掉这道题真心orz. 设状态$(i,j,k)$表示目标棋子在$(i ...

  9. Noip 2016 Day1 题解

    老师让我们刷历年真题, 然后漫不经心的说了一句:“你们就先做做noip2016 day1 吧” ...... 我还能说什么,,,,,老师你这是明摆着伤害我们啊2333333333 预计分数:100+2 ...

随机推荐

  1. NVIDIA TensorRT 让您的人工智能更快!

    NVIDIA TensorRT 让您的人工智能更快! 英伟达TensorRT™是一种高性能深度学习推理优化器和运行时提供低延迟和高通量的深度学习推理的应用程序.使用TensorRT,您可以优化神经网络 ...

  2. Windows相关

    PE WIndows 相关知识 windows 主机防护

  3. oracle中varchar2字段存入blob字段及blob转成varchar2

    CREATE OR REPLACE FUNCTION C2B (b IN CLOB default empty_clob()) RETURN BLOB -- typecasts BLOB to CLO ...

  4. NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day2题解

    上星期打的...题有点水,好多人都AK了 T1排个序贪心就好了 #include<iostream> #include<cstring> #include<cstdlib ...

  5. X day3

    题目 官方题解 T1: 一道水题 #include<iostream> #include<cstring> #include<cstdio> #include< ...

  6. bzoj 4724 [POI2017]Podzielno 二分+模拟

    [POI2017]Podzielno Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 364  Solved: 160[Submit][Status][ ...

  7. ARM汇编程序闪烁灯与其反汇编代码比较

    /* *LED闪烁 *led.s */ #define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 .global _start //把 _start ...

  8. 实体框架(Entity Framework)快速入门--实例篇

    在上一篇 <实体框架(Entity Framework)快速入门> 中我们简单了解的EF的定义和大体的情况,我们通过一步一步的做一个简单的实际例子来让大家对EF使用有个简单印象,看操作步骤 ...

  9. Java多线程之“同步”

    好习惯要坚持,这是我第二篇博文,任务略重,但是要坚持努力!!! 1.竞争条件 首先,我们回顾一下<Java核心技术卷>里讲到的多线程的“竞争条件”.由于各线程访问数据的次序,可能会产生讹误 ...

  10. jedis在线文档网址

    jedis在线文档网址:http://tool.oschina.net/apidocs/apidoc?api=jedis-2.1.0