【20170604校内模拟赛】香蕉
2017-06-11 11:33
316 查看
学长@FallDream所出的一套模拟赛,难度中等稍难,涵盖范围较广。
小Z有\(n\)个香蕉排成了一行。
由于上次比赛小Z没有AK,所以他很不高兴,拿出了他的香蕉锤开始锤香蕉。你已经知道了他锤香蕉的顺序,你想知道,每次他锤的香蕉左右两边第一个还没被锤掉的香蕉是哪一个。
第一行一个数字,表示有\(n\)个香蕉。
接下来\(n\)个数字,第\(i\)个数字表示他第\(i\)次锤的香蕉是哪一个。
输出\(n\)行,每行两个数,表示第\(i\)次锤掉香蕉之后,那个被锤掉的香蕉左右两边第一个还没有被锤掉的香蕉是哪一个?
如果已经没有香蕉了,输出-1
5
2 4 5 3 1
1 3
3 5
3 -1
1 -1
-1 -1
对于50%的数据,$ n \leq 5*10^3 $
对于100%的数据,$ n \leq 5*10^5 $
Time Limit per Test Case: 1000ms
Memory Limit: 128MB
裸题,使用双向链表维护即可。
时间效率\(O(n)\)
小Z喜欢吃香蕉。
小Z种了一棵由\(n\)个节点组成的香蕉树,每个节点都是一个香蕉,且这些节点被\(n-1\)条树枝连接,保证任意两个香蕉之间有且只有一条路径。每条树枝上都有一个权值。小Z想到了一个问题,他想知道所有(两个香蕉之间的路径的权值异或和)的异或和是多少?
第一行一个整数\(n\),表示这棵香蕉树有\(n\)个节点。
接下来\(n-1\)行,每行3个数\(u,v,w\),描述一条连接香蕉\(u\)和香蕉\(v\)且权值为\(w\)的树枝。
输出一个整数,表示题目所求的答案。
3
1 2 1
2 3 2
0
对于40%的数据,\(n \leq 300\)
对于60%的数据,$n \leq 2*10^3 $
对于100%的数据,$ n \leq 5*10^5$ .
Time Limit per Test Case: 1000ms
Memory Limit: 128MB
显然,一条边对答案的贡献次数为这条边以这条边其中一个端点为根时另一个端点的子树大小相乘。
考虑异或的特殊性,我们有如下性质:
\[a\; xor\; b\; xor\; c=(a\; xor\; b)xor\; c=(a xor\; c)xor\; b\]
\[a\; xor\; a=0,a\; xor\; 0=a\]
因此,我们容易发现一条边对答案有贡献,当且仅当这条边的贡献次数为奇数时,且贡献为这条边的权值。
于是我们就可以得出解题方式,dfs一遍即可。
时间效率\(O(n)\)
小Z来到了香蕉川。
香蕉川由\(n\)座香蕉山组成,第i座山有它的高度\(h_{i}\)。小Z准备从左到右爬这里的恰好\(m\)座香蕉山,但他不希望山的高度起伏太大,太过颠簸,会让本就体育不好的他过于劳累。所以他定义了爬山的劳累度是所有爬的相邻的两座山的高度差的绝对值之和。小Z希望他劳累值最小,所以他想问这个劳累值最小能是多少?
第一行两个整数\(n,m\),表示有\(n\)座山且他准备爬其中恰好\(m\)座山。
第二行个数,分别给出每座山的高度\(h_{i}\)。
输出一个整数,表示最小的劳累值。
5 3
1 5 2 3 4
2
对于50%的数据,\(n \leq 300\)
对于100%的数据,\(n \leq 2000 , 1 \leq h_{i} \leq 1000\)
Time Limit per Test Case: 3000ms
Memory Limit: 128MB
首先我们考虑\(n=300\)的情况下,用\(f_{i,j}\)表示选了j座山,第j座山恰好为i的最优值,显然我们是可以比较容易得到下列一个状态转移方程的:
\[f_{i,j}=min(f_{k:1\rightarrow i-1,j-1}+|h_{k}-h_{i}|) \]
接下来我们考虑优化这个DP,考虑将绝对值拆开,然后利用2棵权值线段树加速即可。
时间效率\(O(n^{2} \log_{2}{n} )\)
小Z准备搭建一个香蕉船,因此他需要很多的香蕉。
小Z来到了一个香蕉长廊,第\(i\)个房间有\(a_{i}\)个香蕉。小Z准备选择一些连续的房间并拿走全部的香蕉。出于一些原因,小Z选择的房间数量必须是偶数,并且不小于\(L\)。在此基础上,小Z希望拿到的香蕉的平均数最大,请你告诉他最大的平均数是多少?
第一行有两个整数\(n,L\) ,表示有\(n\)个房间,并且至少选择\(L\)个房间。
接下来一行\(n\)个整数,第\(i\)个整数表示\(a_{i}\) 。
小Z很讨厌小数。如果答案是个整数,请直接输出。否则,请输出一个最简分数,分子和分母之间用/隔开
5 3
1 1 4 1 1
7/4
$n \leq 2*10^5,0 \leq a_{i} \leq 10^9 $
40%的数据满足 \(n \leq 5000\)
保证数据有解
Time Limit per Test Case: 2000ms
Memory Limit: 128MB
二分平均数是多少,并把所有数字减去那么多。
这个二分的值可行,当且仅当存在一段的和大等于0
利用单调栈维护
因为长度必须为偶数,故分奇偶开2个单调栈即可。
时间效率$O(n \log_{2} Ans) $
T1(香蕉锤)
Description
小Z有\(n\)个香蕉排成了一行。
由于上次比赛小Z没有AK,所以他很不高兴,拿出了他的香蕉锤开始锤香蕉。你已经知道了他锤香蕉的顺序,你想知道,每次他锤的香蕉左右两边第一个还没被锤掉的香蕉是哪一个。
Input
第一行一个数字,表示有\(n\)个香蕉。
接下来\(n\)个数字,第\(i\)个数字表示他第\(i\)次锤的香蕉是哪一个。
Output
输出\(n\)行,每行两个数,表示第\(i\)次锤掉香蕉之后,那个被锤掉的香蕉左右两边第一个还没有被锤掉的香蕉是哪一个?
如果已经没有香蕉了,输出-1
Sample Input
5
2 4 5 3 1
Sample Output
1 3
3 5
3 -1
1 -1
-1 -1
Hint
对于50%的数据,$ n \leq 5*10^3 $
对于100%的数据,$ n \leq 5*10^5 $
Time Limit per Test Case: 1000ms
Memory Limit: 128MB
Solution
裸题,使用双向链表维护即可。
时间效率\(O(n)\)
Code
#include <stdio.h> #define MN 500005 #define r register #ifndef Debug #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++) char BB[1<<15],*S=BB,*TT=BB; #endif inline int read(){ r int x; r bool f; r char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } int n,lst[MN],nxt[MN]; int main(){ n=read();for (r int i=1; i<=n; ++i) lst[i]=i-1,nxt[i]=i+1; lst[1]=-1,nxt =-1;for (r int i=1; i<=n; ++i){ r int x=read();printf("%d %d\n",lst[x],nxt[x]); if (lst[x]!=-1) nxt[lst[x]]=nxt[x]; if (nxt[x]!=-1) lst[nxt[x]]=lst[x]; }return 0; }
T2(香蕉树)
Description
小Z喜欢吃香蕉。
小Z种了一棵由\(n\)个节点组成的香蕉树,每个节点都是一个香蕉,且这些节点被\(n-1\)条树枝连接,保证任意两个香蕉之间有且只有一条路径。每条树枝上都有一个权值。小Z想到了一个问题,他想知道所有(两个香蕉之间的路径的权值异或和)的异或和是多少?
Input
第一行一个整数\(n\),表示这棵香蕉树有\(n\)个节点。
接下来\(n-1\)行,每行3个数\(u,v,w\),描述一条连接香蕉\(u\)和香蕉\(v\)且权值为\(w\)的树枝。
Output
输出一个整数,表示题目所求的答案。
Sample Input
3
1 2 1
2 3 2
Sample Output
0
Hint
对于40%的数据,\(n \leq 300\)
对于60%的数据,$n \leq 2*10^3 $
对于100%的数据,$ n \leq 5*10^5$ .
样例解释
1到2的路径的权值异或和是1;2到3是2;1到3是1^2=3,所以答案是1^2^3=0Time Limit per Test Case: 1000ms
Memory Limit: 128MB
Solution
显然,一条边对答案的贡献次数为这条边以这条边其中一个端点为根时另一个端点的子树大小相乘。
考虑异或的特殊性,我们有如下性质:
\[a\; xor\; b\; xor\; c=(a\; xor\; b)xor\; c=(a xor\; c)xor\; b\]
\[a\; xor\; a=0,a\; xor\; 0=a\]
因此,我们容易发现一条边对答案有贡献,当且仅当这条边的贡献次数为奇数时,且贡献为这条边的权值。
于是我们就可以得出解题方式,dfs一遍即可。
时间效率\(O(n)\)
Code
#include <stdio.h> #define MN 500005 #define r register #ifndef Debug #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++) char BB[1<<15],*S=BB,*TT=BB; #endif inline int read(){ r int x; r bool f; r char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } int to[MN<<1],nxt[MN<<1],n,sz[MN],cnt,head[MN],val[MN<<1],ans=0; inline void ins(int x,int y,int v){to[++cnt]=y,nxt[cnt]=head[x],val[cnt]=v;head[x]=cnt;} void dfs(int u,int f){ sz[u]=1;for (r int i=head[u]; i; i=nxt[i]) if (to[i]!=f) dfs(to[i],u),sz[u]+=sz[to[i]],(sz[to[i]]*(n-sz[to[i]]))&1?ans^=val[i]:ans; } int main(){ n=read();for (r int i=1; i<n; ++i){ r int x=read(),y=read(),val=read(); ins(x,y,val);ins(y,x,val); }dfs(1,0);printf("%d",ans); }
T3(香蕉川)
Description
小Z来到了香蕉川。
香蕉川由\(n\)座香蕉山组成,第i座山有它的高度\(h_{i}\)。小Z准备从左到右爬这里的恰好\(m\)座香蕉山,但他不希望山的高度起伏太大,太过颠簸,会让本就体育不好的他过于劳累。所以他定义了爬山的劳累度是所有爬的相邻的两座山的高度差的绝对值之和。小Z希望他劳累值最小,所以他想问这个劳累值最小能是多少?
Input
第一行两个整数\(n,m\),表示有\(n\)座山且他准备爬其中恰好\(m\)座山。
第二行个数,分别给出每座山的高度\(h_{i}\)。
Output
输出一个整数,表示最小的劳累值。
Sample Input
5 3
1 5 2 3 4
Sample Output
2
Hint
对于50%的数据,\(n \leq 300\)
对于100%的数据,\(n \leq 2000 , 1 \leq h_{i} \leq 1000\)
样例解释
小Z可以选择爬1.2.3三座山或者2.3.4三座山,劳累值为1+1=2Time Limit per Test Case: 3000ms
Memory Limit: 128MB
Solution
首先我们考虑\(n=300\)的情况下,用\(f_{i,j}\)表示选了j座山,第j座山恰好为i的最优值,显然我们是可以比较容易得到下列一个状态转移方程的:
\[f_{i,j}=min(f_{k:1\rightarrow i-1,j-1}+|h_{k}-h_{i}|) \]
接下来我们考虑优化这个DP,考虑将绝对值拆开,然后利用2棵权值线段树加速即可。
时间效率\(O(n^{2} \log_{2}{n} )\)
Code
#include <stdio.h> #include <string.h> #include <algorithm> #define r register #define MN 2005 #define M (1<<10) #define min(a,b) ((a)<(b)?(a):(b)) #define inf 0x3f3f3f3f #define getchar() (S==TT&&(TT=(S=BB)+fread(BB,1,1<<15,stdin),TT==S)?EOF:*S++) char BB[1<<15],*S=BB,*TT=BB; inline int read(){ r int x; r bool f; r char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } int Tmi[M<<1],Tma[M<<1]; int f[MN][MN],a[MN],m,n; inline int Qhigh(int k){ r int res=inf; for (k+=M-1; k!=1; k>>=1) if (~k&1) res=min(res,Tma[k^1]); return res; } inline int Qlow(int k){ r int res=inf; for (k+=M+1; k!=1; k>>=1) if (k&1) res=min(res,Tmi[k^1]); return res; } inline void A(int k,int val1,int val2){ Tmi[k+=M]=min(Tmi[k],val1);Tma[k]=min(Tma[k],val2); for (k>>=1; k; k>>=1) Tmi[k]=min(Tmi[k<<1],Tmi[k<<1|1]),Tma[k]=min(Tma[k<<1],Tma[k<<1|1]); } int main(){ memset(f,0x3f,sizeof(f));memset(Tmi,0x3f,sizeof(f)); memset(Tma,0x3f,sizeof(f));n=read(),m=read(); for (r int i=1; i<=n; ++i) a[i]=read(),f[i][1]=0; for (r int i=2; i<=m; ++i){ for (r int j=1; j<i; ++j) A(a[j],f[j][i-1]-a[j],f[j][i-1]+a[j]); for (r int j=i; j<=n; ++j){ f[j][i]=min(Qhigh(a[j])-a[j],Qlow(a[j])+a[j]); A(a[j],f[j][i-1]-a[j],f[j][i-1]+a[j]); } memset(Tmi,0x3f,sizeof(Tmi)); memset(Tma,0x3f,sizeof(Tma)); }r int ans=inf; for (r int i=1; i<=n; ++i) ans=min(ans,f[i][m]); printf("%d\n",ans); }
T4(香蕉船)
Description
小Z准备搭建一个香蕉船,因此他需要很多的香蕉。
小Z来到了一个香蕉长廊,第\(i\)个房间有\(a_{i}\)个香蕉。小Z准备选择一些连续的房间并拿走全部的香蕉。出于一些原因,小Z选择的房间数量必须是偶数,并且不小于\(L\)。在此基础上,小Z希望拿到的香蕉的平均数最大,请你告诉他最大的平均数是多少?
Input
第一行有两个整数\(n,L\) ,表示有\(n\)个房间,并且至少选择\(L\)个房间。
接下来一行\(n\)个整数,第\(i\)个整数表示\(a_{i}\) 。
Output
小Z很讨厌小数。如果答案是个整数,请直接输出。否则,请输出一个最简分数,分子和分母之间用/隔开
Sample Input
5 3
1 1 4 1 1
Sample Output
7/4
Hint
$n \leq 2*10^5,0 \leq a_{i} \leq 10^9 $
40%的数据满足 \(n \leq 5000\)
保证数据有解
Time Limit per Test Case: 2000ms
Memory Limit: 128MB
Solution
二分平均数是多少,并把所有数字减去那么多。
这个二分的值可行,当且仅当存在一段的和大等于0
利用单调栈维护
因为长度必须为偶数,故分奇偶开2个单调栈即可。
时间效率$O(n \log_{2} Ans) $
Code
#include <stdio.h> #define ld double #define ll long long #define eps (1e-12) #define MN 200005 #define r register #define inf 2e9 inline int read(){ r int x; r bool f; r char c; for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-'); for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0'); return f?-x:x; } class que{ public: inline void clear(){h=0;} inline int Qpos(){return pos[1];} inline ld Qnum(){return h?val[1]:inf;} inline void ins(int p,ld v){ while(h&&v<val[h]) --h; pos[++h]=p,val[h]=v; } private: int pos[MN],h; ld val[MN]; }Q1,Q2; ll a[MN];int n,L,ansL,ansR; inline bool check(ld bar){ Q1.clear(); Q2.clear(); for (r int i=L; i<=n; ++i){ ld nv=1.0*a[i]-bar*i; if ((i-L)&1) Q1.ins(i-L,(ld)a[i-L]-bar*(i-L)); else Q2.ins(i-L,(ld)a[i-L]-bar*(i-L)); if (nv-((i&1)?Q1.Qnum():Q2.Qnum())>=-eps) return ansL=(i&1?Q1.Qpos():Q2.Qpos()),ansR=i,1; }return 0; } inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} int main(){ n=read(),L=read(); for (r int i=1; i<=n; ++i) a[i]=read()+a[i-1]; ld L=0,R=inf; #define mid ((L+R)/2.0) for(r int i=1; i<=100; ++i,check(mid)?L=mid:R=mid); ll ans=a[ansR]-a[ansL],ans2=ansR-ansL,g=gcd(ans,ans2); ans/=g,ans2/=g;if (ans2==1) printf("%lld",ans); else printf("%lld/%lld",ans,ans2);return 0; }
相关文章推荐
- 2017.9.2 校内模拟赛
- 2017.9.17校内noip模拟赛解题报告
- 【20171018校内模拟赛】
- 【20171029校内模拟赛】无题
- 【20170906校内模拟赛】
- 20171108校内模拟赛
- 【20170521校内模拟赛】热爱生活的小Z
- 【20170923校内模拟赛】
- 2018.10.17校内模拟赛:T2神光
- NOIP校内模拟赛1
- 2010年9月22号校内ACM省赛前模拟赛教师总结外加部分结题报告
- 20171107校内模拟赛
- 5.13 校内模拟赛
- 【20170915校内模拟赛】
- 2016.10.18出题人丁明朔校内模拟赛反思
- 【20170528校内模拟赛】
- 2017.8.15 校内模拟赛
- 【20170902校内模拟赛】
- 【20170920校内模拟赛】小Z爱学习
- 从猴子够香蕉看新员工培训(转载)