NOIP2012题解

Day1

Vigenère 密码 vigenere

直接模拟就好了,对于那张表找找规律就很短了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 1010
char k[MAX],c[MAX];
char get(char a,char b){return (((b-97)-(a-97)+26)%26)+97;}
int main()
{
scanf("%s",k);scanf("%s",c);
for(int i=0,l=strlen(c),lk=strlen(k);i<l;++i)
{
int x=0;
if(c[i]>='A'&&c[i]<='Z')c[i]+=32,x=-32;
if(k[i%lk]>='A'&&k[i%lk]<='Z')k[i%lk]+=32;
putchar(get(k[i%lk],c[i])+x);
}
puts("");return 0;
}

国王游戏 game

考虑两个人的先后顺序对于答案的影响。分类讨论之后不难发现每个人按照左手乘右手的值从小往大排序显然最优。高精度计算答案即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 1050
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n;
struct peo{int l,r;}p[MAX];
bool operator<(peo a,peo b){return 1ll*a.l*a.r<1ll*b.l*b.r;}
struct Bigint
{
int s[5000],ws;
void init(){s[ws=1]=1;}
void Multi(int b)
{
for(int i=1;i<=ws;++i)s[i]*=b;
for(int i=1;i<=ws;++i)s[i+1]+=s[i]/10,s[i]%=10;
while(s[ws+1])++ws,s[ws+1]+=s[ws]/10,s[ws]%=10;
}
void output(){for(int i=ws;i;--i)printf("%d",s[i]);puts("");}
}ans,now;
bool operator<(Bigint a,Bigint b)
{
if(a.ws!=b.ws)return a.ws<b.ws;
for(int i=a.ws;i;--i)
if(a.s[i]!=b.s[i])return a.s[i]<b.s[i];
return false;
}
Bigint operator/(Bigint a,int b)
{
int r=0;
for(int i=a.ws;i;--i)
{
r=r*10+a.s[i];
a.s[i]=r/b;r%=b;
}
while(a.ws>1&&!a.s[a.ws])--a.ws;
return a;
}
int main()
{
n=read();now.init();now.Multi(read());read();
for(int i=1;i<=n;++i)p[i].l=read(),p[i].r=read();
sort(&p[1],&p[n+1]);
for(int i=1;i<=n;++i)
{
ans=max(ans,now/p[i].r);
now.Multi(p[i].l);
}
ans.output();
return 0;
}

开车旅行 drive

好题。

预处理出在每个位置\(A\)和\(B\)分别会走到哪里,可以用链表实现。接下来把\(A,B\)分别走一次看做一组,直接倍增求解即可。注意最后\(A\)还可能可以单独走一次。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n;
int h[MAX];
int dA[MAX],dB[MAX];
namespace Destination
{
int nt[MAX],lt[MAX],p[MAX],id[MAX];
bool cmp(int a,int b){return h[a]<h[b];}
void upd(int &mx,int &mxx,int i,int j)
{
int s=abs(h[i]-h[j]);if(!j)return;
if(!mx||s<abs(h[i]-h[mx])||(s==abs(h[i]-h[mx])&&h[j]<h[mx]))swap(mx,mxx),mx=j;
else if(!mxx||s<abs(h[i]-h[mxx])||(s==abs(h[i]-h[mxx])&&h[j]<h[mxx]))mxx=j;
}
void Work()
{
for(int i=1;i<=n;++i)p[i]=i;
sort(&p[1],&p[n+1],cmp);
for(int i=1;i<=n;++i)lt[p[i]]=p[i-1],nt[p[i]]=p[i+1];
for(int i=1;i<=n;++i)
{
int mx=0,mxx=0;
upd(mx,mxx,i,lt[i]);upd(mx,mxx,i,lt[lt[i]]);
upd(mx,mxx,i,nt[i]);upd(mx,mxx,i,nt[nt[i]]);
nt[lt[i]]=nt[i];lt[nt[i]]=lt[i];lt[0]=nt[0]=0;
dA[i]=mxx;dB[i]=mx;
}
}
}
int p[17][MAX],sA[17][MAX],sB[17][MAX];
void Query(int S,int X,int &disA,int &disB)
{
disA=disB=0;
for(int i=16;~i;--i)
if(p[i][S]&&X>=sA[i][S]+sB[i][S])
disA+=sA[i][S],disB+=sB[i][S],X-=sA[i][S]+sB[i][S],S=p[i][S];
if(dA[S]&&X>=abs(h[S]-h[dA[S]]))
disA+=abs(h[S]-h[dA[S]]);
}
int main()
{
n=read();
for(int i=1;i<=n;++i)h[i]=read();
Destination::Work();
for(int i=1;i<=n;++i)
{
p[0][i]=dB[dA[i]];
sA[0][i]=abs(h[i]-h[dA[i]]);
sB[0][i]=abs(h[dA[i]]-h[dB[dA[i]]]);
}
for(int i=1;i<17;++i)
for(int j=1;j<=n;++j)
{
p[i][j]=p[i-1][p[i-1][j]];
sA[i][j]=sA[i-1][j]+sA[i-1][p[i-1][j]];
sB[i][j]=sB[i-1][j]+sB[i-1][p[i-1][j]];
}
int X=read();double Rate=1e18;int pos=0;
for(int i=1;i<=n;++i)
{
int disA,disB;double V=0;
Query(i,X,disA,disB);
if(!disB)V=1e18-1;
else V=1.0*disA/disB;
if(V<Rate)Rate=V,pos=i;
else if(V==Rate&&h[i]>h[pos])pos=i;
}
printf("%d\n",pos);
int Q=read();
while(Q--)
{
int S=read(),X=read(),disA,disB;
Query(S,X,disA,disB);
printf("%d %d\n",disA,disB);
}
return 0;
}

Day2

同余方程 mod

\(exgcd\)模板题

#include<iostream>
using namespace std;
int a,b;
void exgcd(int a,int b,int &x,int &y){if(a==0){x=0;y=1;return;}exgcd(b%a,a,y,x);x-=b/a*y;}
int inv(int a,int b){int x,y;exgcd(a,b,x,y);x=(x%b+b)%b;return x;}
int main()
{
cin>>a>>b;
cout<<inv(a,b)<<endl;
return 0;
}

借教室 classroom

二分答案,差分\(check\)。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 1000100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,m,s[MAX],d[MAX],l[MAX],r[MAX],a[MAX];
bool check(int k)
{
for(int i=1;i<=n;++i)a[i]=0;
for(int i=1;i<=k;++i)a[l[i]]+=d[i],a[r[i]+1]-=d[i];
for(int i=1;i<=n;++i){a[i]+=a[i-1];if(a[i]>s[i])return false;}
return true;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)s[i]=read();
for(int i=1;i<=m;++i)d[i]=read(),l[i]=read(),r[i]=read();
int l=1,r=m,ret=m+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))l=mid+1;
else ret=mid,r=mid-1;
}
if(ret>m)puts("0");else printf("-1\n%d\n",ret);
return 0;
}

疫情控制 blockade

好题。

不难发现可以二分答案。考虑如何\(check\)。

首先如果一支军队不能走到根节点那么显然它就停在能够到达的深度最浅的位置一定最优。那么军队分为两类,一类可以到达根节点,即可以控制其他子树,另外一类则不行,那么停留在最优位置不动。接下来,先不考虑可以控制其他子树的军队,\(dfs\)一遍,看看哪些子树需要控制。显然控制在根节点的儿子位置一定最优。显然所有可以控制其他子树的军队全部到达根节点,然后按照剩余移动时间排序。所有需要被覆盖的子树按照距离排序。从小往大一一匹配即可。注意一个问题,考虑一支军队的时候,如果它过来的那个子树还未被覆盖,那么优先覆盖他过来的那棵子树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define MAX 50050
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Line{int v,next,w;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
int n,m,top[MAX],a[MAX];
ll s[16][MAX],dep[MAX];
int p[16][MAX];
void dfs(int u,int ff)
{
dep[u]=dep[ff]+s[0][u];
for(int i=1;i<16;++i)
p[i][u]=p[i-1][p[i-1][u]],s[i][u]=s[i-1][u]+s[i-1][p[i-1][u]];
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)
p[0][e[i].v]=u,s[0][e[i].v]=e[i].w,dfs(e[i].v,u);
}
void dfs(int u,int ff,int id)
{
top[u]=id;
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)dfs(e[i].v,u,id);
}
int Move(int u,ll x)
{
for(int i=15;~i;--i)
if(p[i][u]&&x>=s[i][u])
x-=s[i][u],u=p[i][u];
return u;
}
struct Army{int fr;ll t;}q[MAX];
bool operator<(Army a,Army b){return a.t<b.t;}
bool cmp(int a,int b){return dep[a]<dep[b];}
bool vis[MAX];
void dfs2(int u,int ff)
{
bool fl=true;int son=0;
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff)
{
dfs2(e[i].v,u);++son;
if(!vis[e[i].v])fl=false;
}
if(fl&&son)vis[u]=true;
}
int nd[MAX];
bool check(ll t)
{
int tot=0,sum=0;memset(vis,0,sizeof(vis));
for(int i=1;i<=m;++i)
{
int x=Move(a[i],t);
if(x==1)q[++tot]=(Army){top[a[i]],t-dep[a[i]]};
else vis[x]=true;
}
dfs2(1,0);if(vis[1])return true;
for(int i=h[1];i;i=e[i].next)
if(!vis[e[i].v])nd[++sum]=e[i].v;
sort(&q[1],&q[tot+1]);
sort(&nd[1],&nd[sum+1],cmp);
if(tot<sum)return false;int j=1;
for(int i=1;i<=tot;++i)
{
if(!vis[q[i].fr]){vis[q[i].fr]=true;continue;}
while(j<=sum&&vis[nd[j]])++j;
if(q[i].t>=dep[nd[j]])vis[nd[j]]=true;
}
while(j<=sum&&vis[nd[j]])++j;
return j>sum;
}
int main()
{
n=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read(),w=read();
Add(u,v,w);Add(v,u,w);
}
dfs(1,0);
for(int i=h[1];i;i=e[i].next)dfs(e[i].v,1,e[i].v);
m=read();
for(int i=1;i<=m;++i)a[i]=read();
ll l=0,r=5e13,ret=-1;
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid))ret=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ret);
return 0;
}

NOIP2012题解的更多相关文章

  1. NOIP2012 题解

    Vigenère 密码 这个名字实在打不来... 题解:模拟 #include <cstdio> #include <cstring> +; bool cj; int cl, ...

  2. [NOIP补坑计划]NOIP2012 题解&amp;做题心得

    场上预计得分:100+90+70+100+100+3060=490520(省一分数线245) 题解: D1T1 Vigenère 密码 题面 水题送温暖~~ #include<iostream& ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. [NOIP2012提高]借教室 题解(二分答案+差分)

    [NOIP2012提高&洛谷P1083]借教室 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室 ...

  5. noip2012开车旅行 题解

    题目大意: 给出n个排成一行的城市,每个城市有一个不同的海拔.定义两个城市间的距离等于他们的高度差的绝对值,且绝对值相等的时候海拔低的距离近.有两个人轮流开车,从左往右走.A每次都选最近的,B每次都选 ...

  6. [NOIP2012]国王游戏 题解

    题目大意: n个人排成一排,排头固定,其他可以变.每一个人左右手都有一个整数,一个人的分数为他所有前面的人左手上的数的乘积除以他右手上的数(向下取整),求在整列中最大分数的最小值. 思路: 首先,一切 ...

  7. [NOIP2012]借教室 题解

    题目大意: 有一个n个数的数列,m个操作,第i个操作使[li,ri]区间建di,问第几个操作使数列中出现负数. 思路: 暴力显然过不了,那么就可以优化了,不难想到线段树,显然需要良好的姿势,那么就差分 ...

  8. 【数学】【NOIp2012】同余方程 题解 以及 关于扩展欧几里得与同余方程

    什么是GCD? GCD是最大公约数的简称(当然理解为我们伟大的党也未尝不可).在开头,我们先下几个定义: ①a|b表示a能整除b(a是b的约数) ②a mod b表示a-[a/b]b([a/b]在Pa ...

  9. 【NOIP2012】DAY1+DAY2题解

    不贴代码的原因是我的代码在初中机房.忘记带过来了. DAY 1 T1随便搞,但是字符串相关的题我经常犯蠢 T2 一个结论题,OAO但是需要高精度写. 具体就是按左手的数除右手的数(还是怎么的来着)排个 ...

随机推荐

  1. 函数式 js 接口实现原理,以及 lodash/fp 模块

    函数式 js 接口 之前在 youtube 上看到一个技术视频,讲“underscore.js的接口为什么不好用”,以及什么样的接口更好用.演讲者是 lodash.js 的作者,他提出了一种“全面函数 ...

  2. Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

    前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...

  3. Umbraco(3) - CSS &amp; Javascript(翻译文档)

    原文地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/umbraco3css-javascript/ CSS & Jav ...

  4. 基于 Jenkins 快速搭建持续集成环境--转

    源地址:http://www.ibm.com/developerworks/cn/java/j-lo-jenkins/ 持续集成是一种软件开发实践,对于提高软件开发效率并保障软件开发质量提供了理论基础 ...

  5. tcpclient 类

    1. 构造函数 1) 类对象将套接字与本地系统地址和一个随机的tcp端口号进行绑定. 在默认的tcpclient 对象创建后,必须使用connect方法与远程设备连接. TcpClient tc = ...

  6. [RxJS] Observables can throw errors

    Whenever we are writing code, we need to remember that things may go wrong. If an error happens in a ...

  7. Unity编程标准导引-2.2Unity中的基本概念

    2.2Unity中的基本概念 上述介绍提到了几个概念:游戏对象.场景.资源.相机,这个小节我们来深入了解,同时进行一些实践性操作.不过首先,我们需要大概了解一下Unity的工程文件夹. 2.2.1工程 ...

  8. ubuntu 14.04 安装svn server (subversionedge )

    ubuntu 14.04 安装subversionedge 请仔细阅读安装包自带的readme文件! 1.先去官网,找安装包: http://subversion.apache.org/ http:/ ...

  9. Visual Studio 201~ Code 格式检查

    前言 好的代码格式,有利于阅读和查错,慢慢的有利于养成良好的编码习惯,也可以帮我们找出一些低级错误. StyleCop 在Nuget上搜索stylecop,选择MSBuild的那个版本,安装. 手动编 ...

  10. defer 和 async 区别

    defer saync 共同点: script 标签属性, 控制脚本加载时间,解决script下载阻塞的问题. 区别: defer:推推推荐! 异步加载,所有元素解析完执行. async: 异步加载, ...