2017-10-09离线赛
来源:互联网 发布:yy淘宝兼职可信吗 编辑:程序博客网 时间:2024/06/07 06:04
据说是镇海中学出的题目
大体状况
255/300
T1 xor
题目大意
有一个数列,取一个区间,使区间最大值与次大值异或值最大。
分析
P40
暴力
维护最大值与次大值。
P100
这种题目肯定只有两种方法。
枚举最大值,查找次大值。
枚举次大值,查找最大值。
然后显然是后一种好写。
考虑其匹配的是哪个最大值。
用单调栈处理出前一个大于等于其的值。
设其位置为l,当前位置为r。
如果[l,r]范围扩大,这个答案不变或此数不能成为次大值。
如果[l,r]范围缩小,此数会变成最大值。
前后各扫一遍即可。
代码
然后数组少打一个0减少20分。
感觉是十分低级的错误啊。
#include<bits/stdc++.h>using namespace std;#define Komachi is retarded#define REP(i,a,b) for(int i=(a),i##_end_=(b);i<i##_end_;i++)#define DREP(i,a,b) for(int i=(a),i##_end_=(b);i>i##_end_;i--)#define LL long long#define chkmin(a,b) a=min(a,b)#define chkmax(a,b) a=max(a,b)#define M 2000004void Rd(int &res){ char c;res=0; while((c=getchar())<48); do res=(res<<3)+(res<<1)+(c^48); while((c=getchar())>47);}int n,A[M];struct P40{ void Solve(){ int Ans=0; REP(i,0,n-1){ int x=max(A[i],A[i+1]),y=min(A[i],A[i+1]); chkmax(Ans,x^y); REP(j,i+2,n){ if(A[j]>=x)y=x,x=A[j]; else if(A[j]>y)y=A[j]; chkmax(Ans,x^y); } } printf("%d\n",Ans); }}P40;struct P100{ int Stk[M],Top; void Solve(){ int Ans=0; REP(i,0,n){ while(Top && Stk[Top]<A[i])Top--; if(Top)chkmax(Ans,Stk[Top]^A[i]); Stk[++Top]=A[i]; } Top=0; DREP(i,n-1,-1){ while(Top && Stk[Top]<A[i])Top--; if(Top)chkmax(Ans,Stk[Top]^A[i]); Stk[++Top]=A[i]; } printf("%d\n",Ans); }}P100;int main(){ freopen("xor.in","r",stdin); freopen("xor.out","w",stdout); Rd(n); REP(i,0,n)Rd(A[i]); if(n<=5000)P40.Solve(); else P100.Solve(); return 0;}
T2 atom
题目描述
求一棵看起来非常奇怪的树的子树节点个数。
然而边要自己造,点数达到
分析
P75
那么你就暴力建边暴力DP求一下就好了。
代码实现起来稍微麻烦一些。
P100
因为这个题目的各种性质,
所以剪掉叶节点后点数一下子就变成了
然后叶节点可以排列组合算,
直接DFS或者一次DP处理均可。
代码
这里选择了对每种
然而没有DFS跑得快。
#include<bits/stdc++.h>using namespace std;#define Komachi is retarded#define REP(i,a,b) for(int i=(a),i##_end_=(b);i<i##_end_;i++)#define DREP(i,a,b) for(int i=(a),i##_end_=(b);i>i##_end_;i--)#define LL long long#define chkmin(a,b) a=min(a,b)#define chkmax(a,b) a=max(a,b)int T,n,Case;char C[14];int Base[]={0,1,10,100,1000,10000,100000,1000000,10000000,100000000,404};int Fac[]={1,1,2,6,24,120,720,5040,40320,362880,3628800};struct P100{ static const int M=50004; map<int,int>ID[14]; bool Do[14]; int Re[M],Sz[14][M]; int Next[M],To[M],Head[M],Tim[M],id,tot,tar; void Add_Edge(int u,int v){ if(Tim[u]!=tar)Tim[u]=tar,Head[u]=0; Next[++tot]=Head[u],To[Head[u]=tot]=v; } #define LREP(i,A) for(int i=Head[A];i;i=Next[i]) void Clear(){ tot=id=0; tar++; } void DFS(int A){ Sz[n][A]=1; if(Tim[A]==tar)LREP(i,A) DFS(To[i]),Sz[n][A]+=Sz[n][To[i]]; if(Sz[n][A]==1){ int p=Re[A],k=Fac[n],zero=n; if(p==1)return; REP(i,0,n){ k/=Fac[p%10]; zero-=p%10; p/=10; } k/=Fac[zero]; Sz[n][A]+=k; } } int A[14]; void Build(int pos,int x,int S,bool k){ if(pos>n){ if(!S)return; if(k){ int y=0; REP(i,1,n+1) y+=Base[A[i]]; if(y!=x)Add_Edge(ID[n][y],ID[n][x]); } else ID[n][x]=++id,Re[id]=x; return; } REP(i,0,(n-S)+1) A[pos]=i,Build(pos+1,x+Base[pos]*i,S+i,k); } void Init(){ if(Do[n])return; Clear(); Build(1,0,0,0); Build(1,0,0,1); DFS(ID[n][1]); Sz[n][ID[n][0]=0]=0; Do[n]=1; } void Solve(){ Init(); int x=0,j=0; REP(i,0,n){ if(C[i]-'0'>n){printf("Case #%d: %d\n",++Case,0);return;} j+=C[i]-'0'; x+=Base[i+1]*(C[i]-'0'); } printf("Case #%d: %d\n",++Case,j>n?1:Sz[n][ID[n][x]]); }}P100;int main(){ scanf("%d",&T); while(T--){ scanf("%s",C); n=strlen(C); P100.Solve(); } return 0;}
T3 chocolate
分析
假的T3。
P30
有一个
然后就可以简单贪心。
P60
然后是
感觉还是能贪心。
先喂%p=0,然后%p=1或%p=2都是需要三个相同才能得到一个收益。
然后它们配对的话两个就可以得到一个收益。
所以算一下就好了。
P100
然后是
先想了想枚举一个东西再贪心。
然后发现没有必要。
其实按着上面的思路接着分类讨论一下贪心即可。
具体细节看代码吧。
代码
#include<bits/stdc++.h>using namespace std;#define Komachi is retarded#define REP(i,a,b) for(int i=(a),i##_end_=(b);i<i##_end_;i++)#define DREP(i,a,b) for(int i=(a),i##_end_=(b);i>i##_end_;i--)#define LL long long#define chkmin(a,b) a=min(a,b)#define chkmax(a,b) a=max(a,b)void Rd(int &res){ char c;res=0; while((c=getchar())<48); do res=(res<<3)+(res<<1)+(c^48); while((c=getchar())>47);}#define M 10004 int T,n,p,A[M],Case;struct P30{ int Cnt[4]; void Solve(){ memset(Cnt,0,sizeof(Cnt)); REP(i,0,n)Cnt[A[i]&1]++; int Ans=Cnt[0]+(Cnt[1]>>1)+(Cnt[1]&1); printf("Case #%d: %d\n",++Case,Ans); }}P30;struct P60{ int Cnt[4]; void Solve(){ memset(Cnt,0,sizeof(Cnt)); REP(i,0,n)Cnt[A[i]%3]++; int Ans=min(Cnt[1],Cnt[2]); Cnt[1]-=Ans; Cnt[2]-=Ans; Ans+=(Cnt[1]+3-1)/3; Ans+=(Cnt[2]+3-1)/3; Ans+=Cnt[0]; printf("Case #%d: %d\n",++Case,Ans); }}P60;struct P100{ int Cnt[4]; void Solve(){ memset(Cnt,0,sizeof(Cnt)); REP(i,0,n)Cnt[A[i]%4]++; int Ans=min(Cnt[1],Cnt[3]); Cnt[1]-=Ans; Cnt[3]-=Ans; int p=Cnt[1]==0?3:1; Ans+=(Cnt[2]>>1); Cnt[2]=Cnt[2]&1; if(Cnt[2]){ if(Cnt[p]>=2){ Ans++,Cnt[p]-=2; Ans+=(Cnt[p]+4-1)/4; } else Ans++; } else Ans+=(Cnt[p]+4-1)/4; Ans+=Cnt[0]; printf("Case #%d: %d\n",++Case,Ans); }}P100;int main(){ freopen("chocolate.in","r",stdin); freopen("chocolate.out","w",stdout); Rd(T); while(T--){ Rd(n),Rd(p); REP(i,0,n)Rd(A[i]); if(p==1)printf("Case #%d: %d\n",++Case,n); else if(p==2)P30.Solve(); else if(p==3)P60.Solve(); else P100.Solve(); } return 0;}
总结
十分正常的题目与分数。
时间分配略少了一些,否则应该能写出T2。
T2的P75实现花的时间较多,然而暴力DFS不优化也可以过。
T3是假T3,T1失误。
- 2017-10-09离线赛
- 2017-10-10离线赛
- 2017-10-07离线赛
- 2017-10-06离线赛
- 2017-10-12离线赛
- 2017-10-15离线赛
- 2017-10-16离线赛
- 2017-10-17离线赛
- 2017-10-18离线赛
- 2017-10-10离线赛总结
- 2017-10-3离线赛小结
- 2017-10-4离线赛总结
- 2017-10-6离线赛总结
- 2017-10-7离线赛题解
- 2017-10-7离线赛总结
- 2017-10-8离线赛总结
- 2017-10-9离线赛总结
- 2017-10-12离线赛总结
- 工作的那点事儿
- Spring3.x 版本和 JDK1.8 不兼容
- 完美解决前端跨域之 easyXDM 的使用和解析
- 打地鼠游戏之游戏倒计时
- 自定义仪表盘
- 2017-10-09离线赛
- VSTO Office二次开发应用程序键盘鼠标钩子
- 人群分析、人群计数 开源代码文献及数据库
- Altium Designer如何打开PROTEL 99SE DDB文件
- 简单工厂、抽象工厂和工厂模式的总结
- 常用排序算法稳定性分析(转载)
- web--前端之js代码3
- Flex 学习之路之六 用户接口user interface 应用效果effect
- Vision_字符串_字符串哈希(BKDR Hash)