NOIP2012提高组

Posted Child-Single

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2012提高组相关的知识,希望对你有一定的参考价值。

Day1

T1vigenere密码

题目链接

vijos截得不全导致题意可能会理解错,注意小写字母应该是先转大写进行变换,再根据情况看是否需要再转成小写。

然后,然后就没了啊。

 1 #include<cstdio>
 2 #include<cstring>
 3 char ch[105],tt[1005],an[1005];
 4 int len,le,mi[105];
 5 int main(){
 6     scanf("%s %s",ch+1,tt+1);
 7     len=strlen(ch+1);le=strlen(tt+1);
 8     for(int i=1;i<=len;i++){
 9         if(ch[i]>=\'a\')ch[i]=ch[i]-(\'a\'-\'A\');
10         mi[i]=ch[i]-130;
11     }
12     int h=1;
13     for(int i=1;i<=le;i++,h++){
14         if(h>len)h=1;
15         int p=tt[i]>=\'a\'?tt[i]-(\'a\'-\'A\'):tt[i];
16         p-=65;
17         for(int x=\'A\';x<=\'Z\';x++)if((x+mi[h])%26==p){an[i]=x;break;}
18         if(tt[i]>=\'a\')an[i]+=\'a\'-\'A\';
19     }
20     for(int i=1;i<=le;i++)printf("%c",an[i]);
21     return 0;
22 }
D1 T1

T2国王游戏

题目链接

对于两个人的顺序安排,不会对前后的其他人造成影响。

设两个人左右手上数字分别为l1,r1;l2,r2。

那么答案就是min(max(l1/r2,1/r1),max(l2/r1,1/r2))。-->忽略前面的数,反正也会被约掉

1.当r1>r2时:

  l1/r2>1/r1;l1/r2>1/r2;

所以答案是min(l1/r2,l2/r1)。

2.当r2>r1时:

  l2/r1>1/r2;l2/r1>1/r1;

所以答案tm还是min(l1/r2,l2/r1)。

综上答案只跟l1/r2和l2/r1的大小的关系有关。

交叉相乘得:

当l1*r1>l2*r2时,l1/r2>l2/r1;否则l1/r2<l2/r1。

那么只要按l*r从小到大排个序就好啦。

对了好像还有个高精乘低精和高精除低精......

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<cmath>
 6 typedef long long LL;
 7 const int N=1005;
 8 int read(){
 9     int ans=0,f=1;char c=getchar();
10     while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();}
11     while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-48;c=getchar();}
12     return ans*f;
13 }
14 struct node{
15     LL li,ri,wi;
16     bool operator <(const node&p)const{return p.wi<wi;}
17 };
18 std::priority_queue<node>q;
19 LL mxa[5000],ch[5000],y[5000];
20 void mul(LL x[],LL d){
21     LL jin=0,wei=log(d)/log(10)+1;
22     x[0]+=wei;
23     for(int i=1;i<=x[0];i++){
24         x[i]=x[i]*d+jin;
25         jin=x[i]/10;
26         x[i]%=10;
27     }
28     while(x[x[0]]==0)x[0]--;
29 }
30 void mol(LL x[],LL d){
31     LL sh=0;
32     for(int i=x[0];i>=1;i--){
33         sh=sh*10+x[i];
34         x[i]=sh/d;
35         sh=sh%d;
36     }
37     while(x[x[0]]==0)x[0]--;
38 }
39 void max(){
40     if(y[0]<mxa[0])return;
41     if(mxa[0]<y[0]){memcpy(mxa,y,sizeof(mxa));return;}
42     for(int i=mxa[0];i>=1;i--)
43         if(y[i]>mxa[i]){memcpy(mxa,y,sizeof(mxa));return;}
44 }
45 int main(){
46     int n=read();
47     LL op=read();read();
48     while(op)ch[++ch[0]]=op%10,op/=10;
49     for(int i=1,a,b;i<=n;i++){
50         a=read();b=read();
51         q.push((node){a,b,a*b});
52     }
53     for(int i=1;i<=n;i++){
54         node p=q.top();q.pop();
55         for(int i=0;i<=ch[0];i++)y[i]=ch[i];
56         mol(y,p.ri);
57         max();
58         mul(ch,p.li);
59     }
60     for(int i=mxa[0];i>=1;i--)printf("%lld",mxa[i]);
61     return 0;
62 }
D1 T2

T3开车旅行

题目链接

从后往前预处理出离每个点的最近、次近距离(平衡树),那么第一第二问就都是一个倍增可以解决的东西了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<set>
 5 #define mem(a,p) memset(a,p,sizeof(a))
 6 typedef long long LL;
 7 const int N=1e5+10;
 8 struct node{
 9     int hi,id;
10     bool operator <(const node&p)const{return p.hi>hi;}
11 };
12 struct no{int hi,yu,id;};
13 bool cmp(no a,no b){return a.hi!=b.hi?a.hi<b.hi:a.yu<b.yu;}
14 int n,h[N],m;
15 typedef std::multiset<node>myset;
16 typedef myset::iterator IT;
17 myset se;
18 LL ato[N][22],bto[N][22];
19 int g[N][22],to[N],co[N];
20 int read(){
21     int ans=0,f=1;char c=getchar();
22     while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();}
23     while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-48;c=getchar();}
24     return ans*f;
25 }
26 int main(){
27     n=read();
28     for(int i=1;i<=n;i++)h[i]=read();
29     se.insert((node){h[n],n});se.insert((node){h[n-1],n-1});
30     bto[n-1][0]=abs(h[n]-h[n-1]);to[n-1]=n;
31     for(int i=0;i<=n;i++)
32         for(int j=0;j<=20;j++)ato[i][j]=bto[i][j]=2e9;
33     for(int i=n-2;i>=1;i--){
34         IT it=se.lower_bound((node){h[i],i});
35         IT it0=it;
36         no q[5];int tot=0;
37         if(it!=se.end()){
38             q[++tot]=(no){abs(it->hi-h[i]),it->hi,it->id};
39             it++;
40             if(it!=se.end())q[++tot]=(no){abs(it->hi-h[i]),it->hi,it->id};
41         }
42         if(it0!=se.begin()){
43             it0--;q[++tot]=(no){abs(h[i]-it0->hi),it0->hi,it0->id};
44             if(it0!=se.begin())it0--,q[++tot]=(no){abs(h[i]-it0->hi),it0->hi,it0->id};
45         }
46         se.insert((node){h[i],i});
47         if(tot<=1)continue;
48         std::sort(q+1,q+1+tot,cmp);
49         ato[i][0]=q[2].hi;to[i]=q[1].id;g[i][0]=q[2].id;co[i]=q[2].id;
50         if(to[q[2].id])bto[i][0]=abs(h[to[q[2].id]]-h[q[2].id]),g[i][0]=to[q[2].id];
51     }
52     for(int i=n;i>=1;i--){
53         for(int j=1;i+(1<<j)<=n;j++){
54             g[i][j]=g[g[i][j-1]][j-1];
55             ato[i][j]=ato[i][j-1]+ato[g[i][j-1]][j-1];
56             bto[i][j]=bto[i][j-1]+bto[g[i][j-1]][j-1];
57         }
58     }
59     int x0=read();double mni=2e9;int id=0;
60     for(int i=1;i<=n;i++){
61         LL sa=0,sb=0;int i0=i,xx=x0;
62         bool fl=0;
63         for(int j=20;j>=0;j--){
64             if((ato[i][j]+bto[i][j]>xx&&j)||(!j&&ato[i][j]>xx))continue;
65             sa+=ato[i][j];
66             xx-=ato[i][j];
67             if(bto[i][j]>xx){fl=1;break;}
68             sb+=bto[i][j];xx-=bto[i][j];
69             i=g[i][j];
70         }
71         if(!fl&&ato[i][0]<=xx)sa+=ato[i][0],i=co[i];
72         i=i0;    
73         if(sb==0)continue;
74         if(mni==sa*1.0/sb&&h[id]<h[i])id=i;
75         else if(mni>sa*1.0/sb)mni=sa*1.0/sb,id=i;
76     }
77     printf("%d\\n",id);m=read();
78     for(int i=1;i<=m;i++){
79         LL si=read(),xi=read();
80         LL sa=0,sb=0;int fl=0;
81         for(int j=20;j>=0;j--)
82             if((j&&ato[si][j]+bto[si][j]<=xi)||(!j&&ato[si][0]<=xi)){
83                 sa+=ato[si][j];xi-=ato[si][j];
84                 if(bto[si][j]>xi){fl=1;break;}
85                 xi-=bto[si][j];sb+=bto[si][j];
86                 si=g[si][j];
87             }
88         if(!fl&&ato[si][0]<=xi)sa+=ato[si][0],si=co[si];
89         printf("%lld %lld\\n",sa,sb);
90     }
91     return 0;
92 }
D1 T3

 


 

Day2

T1同余方程

以前的博客->戳这里

 

T2借教室

题目链接

二分第一个出现冲突的点,然后就差分前缀和判si[i]是否大于d[i]即可。复杂度O(nlog(n))。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 const int N=1e6+5;
 5 int read(){
 6     int ans=0,f=1;char c=getchar();
 7     while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();}
 8     while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-48;c=getchar();}
 9     return ans*f;
10 }
11 int n,m;
12 int di[N],dj[N],si[N],sj[N];
13 int tr[N];
14 bool check(int x){
15     memset(tr,0,sizeof(tr));
16     for(int i=1;i<=x;i++){
17         tr[si[i]]+=dj[i];tr[sj[i]+1]-=dj[i];
18     }
19     int sum=0;
20     for(int i=1;i<=n;i++){
21         sum+=tr[i];
22         if(sum>di[i])return 0;
23     }
24     return 1;
25 }
26 int main(){
27     n=read();m=read();
28     for(int i=1;i<=n;i++)di[i]=read();
29     for(int i=1;i<=m;i++){
30         dj[i]=read();si[i]=read();sj[i]=read();
31     }
32     int l=0,r=m+1;
33     while(l<r-1){
34         int mid=(l+r)>>1;
35         if(check(mid))l=mid;
36         else r=mid;
37     }
38     if(l==m)printf("0");
39     else printf("-1\\n%d",l+1);
40     return 0;
41 }
D2 T2

T3疫情控制

题目链接

挺难的一道题,然而我之前一个错的很离谱的贪心居然能过vijos上的全部数据......建议写完也去洛谷那边交一下......

不合法无非就是军队数小于根节点的孩子数,没什么难度。

二分一个时间,然后对于每支军队都尽量往上走。

能走到根节点的军队入队,按照剩余可用时间从小到大排序;到不了的就停在最多能走到的点打个标记就行。

dfs根的每棵子树,记一下当前子树是否还有叶子没被控制,有的话记录一下这棵子树里能走到根的最深点-->last(因为它最没用),然后根的次子节点入队。

将子节点构成的队按距离从小到大排序。

枚举每支军队,如果它原来属于子树还没被覆盖,就让它回到它原来的子树去,否则就把离根最近的子节点分配给它,当然到达不了就算了。

判合法就很明显了吧......

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define mem(a,p) memset(a,p,sizeof(a))
  5 typedef long long LL;
  6 const int N=5e4+7;
  7 using std::sort;
  8 int n,m,first[N],tot=0,si[N],son[N],op;
  9 int gr[N][22],deep[N];
 10 LL dis[N][22],tofa[N];
 11 struct node{int ne,to;LL w;}e[N*2];
 12 struct no{LL w;int id;}q[N],st[N];
 13 bool cmp(no a,no b){return a.w<b.w;}
 14 int read(){
 15     int ans=0,f=1;char c=getchar();
 16     while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();}
 17     while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-48;c=getchar();}    
 18     return ans*f;
 19 }
 20 void ins(int u,int v,int w){
 21     e[++tot]=(node){first[u],v,w};first[u]=tot;
 22 }
 23 void dfs(int x,int fa){
 24     for(int i=1;(1<<i)<=deep[x];i++){
 25         gr[x][i]=gr[gr[x][i-1]][i-1];
 26         dis[x][i]=dis[x][i-1]+dis[gr[x][i-1]][i-1];
 27     }
 28     for(int i=first[x];i;i=e[i].ne){
 29         int to=e[i].to;
 30         if(to==fa)continue;
 31         gr[to][0]=x;dis[to][0]=e[i].w;
 32         deep[to]=deep[x]+1;
 33         tofa[to]=tofa[x]+e[i].w;
 34         son[x]++;
 35         dfs(to,x);
 36     }
 37 }
 38 bool ok[N],flag[N];
 39 int last;
 40 void work(int x,int fa,bool&le,bool p){
 41     for(int i=first[x];i;i=e[i].ne){
 42         int to=e[i].to

以上是关于NOIP2012提高组的主要内容,如果未能解决你的问题,请参考以下文章

1402Vigenère密码(Noip2012提高组第1题)

noip提高组2012 借教室(luogu 1083)

NOIP提高组2012 借教室

刷题总结——疫情控制(NOIP2012提高组)

noip2012——提高组——借教室

NOIP2012提高组