NOIP2017 赛前模拟 7.24
来源:互联网 发布:意大利的军事实力 知乎 编辑:程序博客网 时间:2024/06/05 07:33
本次考试三道题据出题人的意思都是模板题,T1单调队列模板,T2数位DP模板,T3线段树模板,但由于前两个模板都不熟悉,考试的时候不敢写,线段树也写炸了,最后只有50分。
T1:
题目描述:
在一个包含 n 个元素的数组上,有一个长度为 k 的窗户在从左向右滑动。窗户每滑动到一个位置,我们都可以看到 k 个元素在窗户中。如下的例子所示,假设数组为 [1 3 -1 -3 5 3 6 7],而 k 等于 3 :
输入格式
输入的第一行包括两个整数 n,k ,n 表示数组的长度,k 表示窗户的长度。
接下来一行包括 n 个整数,表示这个 n 个元素的数组。
输出格式
输出包含两行,每行包括 n-k+1 个整数。
第一行表示窗户从左到右滑动过程中的最小值。
第二行表示窗户从左到右滑动过程中的最大值。
备注
【数据范围】
对于 100% 的数据,3<=n<=1000000,1<=k<=n,数组中的每个元素均在 int 范围内。
题意:每次选k个数,统计最大值和最小值。所以在我无法打出正解时,想到线段树的区间查询,勉强得了50分,DZY也是线段树但A了,我也没办法。
正解:维护两个单调队列,里面存的是最小值和最大值的下标,一个是维护最小值,一个是维护最大值。每次打新的数压入队尾,先考虑维护最小值的队列,如果前面的数比他还大,说明这些数都无法对答案产生共贡献,就直接r- - (队尾的编号),就将其往前移,最大值也是如此
#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<ctime>#include<iomanip>#include<iostream>#include<cctype>using namespace std;const int N =1e6+5;int n,k,q1[N],q2[N],a[N],ans1[N],ans2[N],buf[1000];//---------------------inline int Readint(){ int i=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0'; return i*f;}//---------------------inline void W(int x) //这道题因为数据比较大,输出优化{ if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;} while(x)buf[++buf[0]]=x%10,x/=10; while(buf[0])putchar('0'+buf[buf[0]--]);}//---------------------int main(){ freopen("window.in","r",stdin); //freopen("window.out","w",stdout); n=Readint(),k=Readint(); for(int i=1;i<=n;i++) a[i]=Readint(); int l1=0,l2=0,r1=1,r2=1; for(int i=1;i<=n;i++){ while(l1<=r1 && q1[l1]<=i-k) l1++; //最小值的队列 while(l2<=r2 && q2[l2]<=i-k) l2++; //最大值的队列 while(l1<=r1 && a[i]<=a[q1[r1]]) r1--; //比他小就一直减 q1[++r1]=i; while(l2<=r2 && a[i]>=a[q2[r2]]) r2--; //比他大就一直减 q2[++r2]=i; ans1[i]=a[q1[l1]]; ans2[i]=a[q2[l2]]; } for(int i=k;i<=n;i++) W(ans1[i]),putchar(' '); cout<<endl; for(int i=k;i<=n;i++) W(ans2[i]),putchar(' '); return 0;}
T2: 裸的数位DP
题目描述:
CLC NOIP2015 惨跪,他依稀记得他的准考证号是 37(其实是假的),现在CLC又将要面临一场比赛,他希望准考证号不出现 37(连续),同时他又十分讨厌 4 ,所以也不希望 4 出现在准考证号中。现在他想知道在 A 和 B 之间有多少合法的准考证号
数位Dp 不解释了
#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<iomanip>#include<iostream>#include<cmath>#include<ctime>#include<cctype>using namespace std;int x,y,a[20],dp[20][2];//---------------------inline int Readint(){ int i=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0'; return i*f;}//---------------------/*pos是当前枚举到的位数,pre为前一位的数,为了判断是否为3,sta为当前的状态,limit是判断最大能不能枚举到9;*///---------------------inline int dfs(int pos,int pre,int sta,int limit) { if(pos==-1) return 1; if(!limit && dp[pos][sta]!=-1) return dp[pos][sta]; int up= limit ? a[pos] : 9; int tmp=0; for(int i=0;i<=up;i++){ if(pre==3 && i==7) continue; if(i==4) continue; tmp+=dfs(pos-1,i,i==3,limit && i==a[pos]); } if(!limit) dp[pos][sta]=tmp; return tmp;}//---------------------inline int solve(int x){ int pos=0; while(x) //算出每一位数 { a[pos++]=x%10; x=x/10; } return dfs(pos-1,-1,0,true);}//---------------------int main(){ x=Readint(),y=Readint(); memset(dp,-1,sizeof(dp)); cout<<solve(y)-solve(x-1); //统计[0,y]和[0,x-1]的值相减 return 0;}
T3:
题目描述:
万恶的大头又出现了!他正在玩一个智障游戏:打怪兽。
现在大头的屏幕上出现了一排怪兽,每只怪兽头上有一个血条,每次大头可以选择一个区间进行攻击,攻击值为 K ,这个区间中血量小于 K 的怪兽都会被大头无情地干掉,当然怪兽不会坐以待毙,对于一个区间的怪兽,他们会在某个时刻血量同时加 X 。
头头虽然很大,但是 IQ 并不高,在座的各位选手都不知道比他高到哪里去了。这个时候大头使出了大招——作弊器,然而大头的作弊器并不高级只能将选择的区间内血量为 7 的倍数的怪兽干掉,问:他能干掉多少怪兽?
输入格式
第一行一个正整数 n ;
接下来 n 行 n 个整数;
再接下来一个正整数 Q ,表示操作的个数;
接下来 Q 行每行若干个整数。如果第一个数是 add ,后接 3 个正整数 a,b,X,表示在区间 [a,b] 内每个数增加 X,如果是 count,表示统计区间 [a,b] 能被 7 整除的个数。
正解:线段树打标记,统计每个区间内数值与7取模和 为 0,1,2,3,4,5,6 的个数 ,最后只用暑促余数为0的个数即可
#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<ctime>#include<iomanip>#include<iostream>#include<cctype>using namespace std;const int N = 1e5+5;int a[N],n,m,x,y,z,num;int sum[N<<2][10],add[N<<2],tmp[10];char s[10];//---------------------inline int Readint(){ int i=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<1)+(i<<3)+ch-'0'; return i*f;}//---------------------inline void update(int root){ for(int i=0;i<=6;i++) sum[root][i]=sum[root<<1][i]+sum[root<<1|1][i];}//---------------------inline void mode(int k,int x){ memset(tmp,0,sizeof(tmp)); for(int i=0;i<=6;i++) tmp[i]=sum[k][i]; for(int i=0;i<=6;i++) sum[k][(i+x)%7]=tmp[i];}//---------------------void Pushdown(int k){ if(add[k]) { add[k<<1]=(add[k<<1]+add[k])%7,mode(k<<1,add[k]); add[k<<1|1]=(add[k<<1|1]+add[k])%7,mode(k<<1|1,add[k]); add[k]=0; }}//---------------------void build(int k,int l,int r){ if(l==r) { sum[k][a[l]]++; return; } int mid=l+r>>1; build(k<<1,l,mid),build(k<<1|1,mid+1,r); update(k);}//---------------------void modify(int k,int l,int r,int x,int y,int v){ if(x<=l&&r<=y) { memset(tmp,0,sizeof(tmp)); mode(k,v); add[k]=(add[k]+v)%7; return; } Pushdown(k); int mid=l+r>>1; if(y<=mid)modify(k<<1,l,mid,x,y,v); else if(x>mid)modify(k<<1|1,mid+1,r,x,y,v); else modify(k<<1,l,mid,x,mid,v),modify(k<<1|1,mid+1,r,mid+1,y,v); update(k);}//---------------------inline int Query(int k,int l,int r,int x,int y){ if(x<=l&&r<=y) return sum[k][0]; Pushdown(k); int mid=(l+r)>>1; if(y<=mid) return Query(k<<1,l,mid,x,y); else if(x>mid) return Query(k<<1|1,mid+1,r,x,y); else return Query(k<<1,l,mid,x,y)+Query(k<<1|1,mid+1,r,x,y);}//---------------------int main(){ freopen("seg.in","r",stdin); //freopen("seg.out","w",stdout); n=Readint(); for(int i=1;i<=n;i++) a[i]=Readint()%7; build(1,1,n); m=Readint(); for(int i=1;i<=m;i++){ scanf("%s",s); if(s[0]=='a'){ x=Readint(),y=Readint(),z=Readint()%7; modify(1,1,n,x,y,z); } if(s[0]=='c') { x=Readint(),y=Readint(); cout<<Query(1,1,n,x,y)<<endl; } } return 0;}
- NOIP2017 赛前模拟 7.24
- NOIP2017 赛前模拟(2017.10.6)
- NOIP2017赛前模拟 分玩具
- NOIP2017赛前模拟 字符串(AC自动机)
- NOIP2017赛前模拟(2017.10.19)
- NOIP2017赛前模拟(2017.10.20)
- NOIP2017赛前模拟 Table(双向链表)
- NOIP2017赛前模拟(2017.10.23)
- NOIP2017赛前模拟 Graph (2017.10.24)
- NOIP2017赛前模拟 (2017.10.17)考试总结
- NOIP2017 赛前模拟(2017.10.30)考试总结
- NOIP2017赛前模拟 Game DP (2017.10.30)
- NOIP2017赛前模拟 STAR (合理证明复杂度)
- NOIP2017赛前模拟(2017.10.31)考试总结
- NOIP2017赛前模拟 纸袋(并查集)
- NOIP2017 赛前集训
- NOIP2017 赛前总结
- NOIP2017赛前经验总结
- socket多线程服务器网络通信
- 做好了监控报警,创业公司如何搭建强壮的SaaS服务
- turtle库绘制五角星
- Java获取系统时间
- dp,sp,px区别,dpi,dip区别
- NOIP2017 赛前模拟 7.24
- Webpack 入门(一):安装 / 打包 / 命令行
- cat命令
- 成为无可替代,从提升自己的贡献开始!
- Codeforces Round #425 (Div. 2) B. Petya and Exam(字符串处理)
- GCD HDU
- D. Misha, Grisha and Underground(LCA 倍增)
- PL/SQL学习总结(1)
- 【ReviewBoard】安装与配置