170611 NOIP模拟赛
第一题没做出来不应该;
第二题不难想,就是写起来很麻烦;
第三题因为学了挺久的splay就直接写的splay,没太在意常数问题,一般情况下,第k值问题主席树是比splay稍快的;
盘子序列
【题目描述】
有 n 个盘子。盘子被生产出来后,被按照某种顺序摞在一起。初始盘堆中如果一
个盘子比所有它上面的盘子都大,那么它是安全的,否则它是危险的。称初始盘堆为
A,另外有一个开始为空的盘堆 B。为了掩盖失误,生产商会对盘子序列做一些“处
理”,每次进行以下操作中的一个:(1)将 A 最上面的盘子放到 B 最上面;(2)将 B 最上
面的盘子给你。在得到所有n个盘子之后,你需要判断初始盘堆里是否有危险的盘子。
【输入格式】
输入文件包含多组数据(不超过 10 组)
每组数据的第一行为一个整数 n
接下来 n 个整数,第 i 个整数表示你收到的第 i 个盘子的大小
【输出格式】
对于每组数据,如果存在危险的盘子,输出”J”,否则输出”Y”
【样例输入】
3
2 1 3
3
3 1 2
【样例输出】
Y
J
【数据范围】
20%的数据保证 n<=8
80%的数据保证 n<=1,000
100%的数据保证 1<=n<=100,000,0<盘子大小<1,000,000,000 且互不相等
思路
倒序栈模拟;
代码实现
1 #include<cstdio> 2 #include<cstring> 3 const int maxn=1e5+10; 4 int n; 5 int a[maxn],b[maxn],bs,c[maxn],cs; 6 int main(){ 7 freopen("disk.in","r",stdin); 8 freopen("disk.out","w",stdout); 9 while(scanf("%d",&n)!=EOF){ 10 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 11 for(int i=n;i>0;i--){ 12 if(!bs||b[bs]<a[i]) b[++bs]=a[i]; 13 else while(bs&&b[bs]>a[i]) c[++cs]=b[bs--]; 14 } 15 while(bs) c[++cs]=b[bs--]; 16 for(bs=2;bs<=n;bs++) if(c[bs]>c[bs-1]) break; 17 if(bs>n) puts("Y"); 18 else puts("J"); 19 bs=cs=0; 20 memset(b,0,sizeof(b)); 21 memset(c,0,sizeof(c)); 22 } 23 return 0; 24 }
lazy的不想优化逻辑,时间十分充足了。
四轮车
【题目描述】
在地图上散落着 n 个车轮,小 J 想用它们造一辆车。要求如下:
1. 一辆车需要四个车轮,且四个车轮构成一个正方形
2. 车轮不能移动
你需要计算有多少种造车的方案(两个方案不同当且仅当所用车轮不全相同,坐
标相同的两个车轮视为不同车轮)。
【输入格式】
第一行一个整数 n
接下来 n 行,每行两个整数 x y,表示在(x,y)处有一个车轮
【输出格式】
一行一个整数,表示方案数
【样例输入】
9
0 0
1 0
2 0
0 2
1 2
2 2
0 1
1 1
2 1
【样例输出】
6
【数据范围】
30%的数据保证 n ≤ 30
100%的数据保证 1 ≤ n ≤ 1000;|x|,|y| < 20000
思路
枚举两个点确定图形各个点的位置;
对于地图上某个位置有多少车轮可以用map存;
题解给出的是hash坐标;
代码实现
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 10010 6 using namespace std; 7 int n,ans[maxn],x1,x2,x3,x4,y1,y2,y3,y4,xx[maxn],yy[maxn],p1,p2; 8 struct node{int x,y;}P[maxn]; 9 int cmp(const node &a,const node &b){return a.x<b.x;} 10 int Abs(int a){return a<0?-a:a;} 11 void Add(){ 12 ans[1]++; 13 for(int i=1;i<=ans[0];i++) if(ans[i]>9) ans[i]%=10,ans[i+1]++; 14 if(ans[ans[0]+1])ans[0]++; 15 } 16 void Cal(int i,int j){ 17 x1=xx[i],y1=yy[i],x2=xx[j],y2=yy[j]; 18 int a=Abs(y1-y2),b=Abs(x1-x2); 19 int c=Abs(a-b); 20 if(c%2) x3=x4=y3=y4=0; 21 else{ 22 c>>=1; 23 if(a<b) x3=x1+c,y3=y2+c,x4=x2-c,y4=y1-c; 24 else x3=x1-c,y3=y2-c,x4=x2+c,y4=y1+c; 25 } 26 } 27 bool Judge(){ 28 if(!x3&&!x4&&!y3&&!y4)return 0; 29 int falg=0,flag=0; 30 p1=lower_bound(xx+1,xx+1+n,x3)-xx; 31 p2=upper_bound(xx+1,xx+1+n,x3)-xx; 32 for(int i=p1;i<p2;i++){ 33 if(xx[i]!=x3) return 0; 34 if(yy[i]==y3){falg=1;break;} 35 } 36 p1=lower_bound(xx+1,xx+1+n,x4)-xx; 37 p2=upper_bound(xx+1,xx+1+n,x4)-xx; 38 for(int i=p1;i<p2;i++){ 39 if(xx[i]!=x4) return 0; 40 if(yy[i]==y4){flag=1;break;} 41 } 42 return falg&&flag; 43 } 44 int main(){ 45 freopen("car.in","r",stdin); 46 freopen("car.out","w",stdout); 47 scanf("%d",&n),ans[0]=1; 48 for(int i=1;i<=n;i++) scanf("%d%d",&P[i].x,&P[i].y); 49 sort(P+1,P+1+n,cmp); 50 for(int i=1;i<=n;i++) xx[i]=P[i].x,yy[i]=P[i].y; 51 for(int i=1;i<=n;i++) 52 for(int j=i+1;j<=n;j++){ 53 if(yy[i]>=yy[j])continue; 54 Cal(i,j); 55 if(Judge()) Add(); 56 } 57 for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); 58 return 0; 59 }
再次感谢峰峰学长!
点名
【题目描述】
在J班的体育课上,同学们常常会迟到几分钟,但体育老师的点名却一直很准时。
老师只关心同学的身高,他会依次询问当前最高的身高,次高的身高,第三高的身高,
等等。在询问的过程中,会不时地有人插进队伍里。你需要回答老师每次的询问。
【输入格式】
第一行两个整数 n m,表示先后有 n 个人进队,老师询问了 m 次
第二行 n 个整数,第 i 个数 Ai 表示第 i 个进入队伍的同学的身高为 Ai
第三行 m 个整数,第 j 个数 Bj 表示老师在第 Bj 个同学进入队伍后有一次询问
【输出格式】
m 行,每行一个整数,依次表示老师每次询问的答案。数据保证合法
【样例输入】
7 4
9 7 2 8 14 1 8
1 2 6 6
【样例输出】
9
9
7
8
【样例解释】
(9){No.1 = 9}; (9 7){No.2 = 9}; (9 7 2 8 14 1){No.3 = 7; No.4 = 8}
【数据范围】
40%的数据保证 n ≤ 1000
100%的数据保证 1 ≤ m ≤ n ≤ 30000;0 ≤ Ai < 232
思路
splay裸题,好吧我splay卡常数了;//好吧,我没过是因为没有离散化。。。这道题有写离散化,Spoj 10628. Count on a tree。
也可以用主席树来做,能过;
正解好像是双堆;
!int∈[-231,231]
代码实现
1 #include<cstdio> 2 const long long maxn=3e5+10; 3 long long n,m,a,b; 4 long long ss[maxn]; 5 long long rt,hd; 6 long long t[maxn],f[maxn],sz[maxn],am[maxn],s[maxn][2]; 7 void rot(long long x){ 8 long long y=f[x],z=f[y],l,r; 9 l=s[y][0]==x?0:1,r=l^1; 10 if(y==rt) rt=x; 11 else{ 12 if(s[z][0]==y) s[z][0]=x; 13 else s[z][1]=x; 14 } 15 f[x]=z,f[y]=x,f[s[x][r]]=y; 16 s[y][l]=s[x][r],s[x][r]=y; 17 sz[y]=sz[s[y][0]]+sz[s[y][1]]+am[y]; 18 sz[x]=sz[s[x][0]]+sz[s[x][1]]+am[x]; 19 } 20 void splay(long long x){while(x!=rt) rot(x);} 21 void ins(long long k,long long x,long long fa){ 22 if(!rt){rt=++hd,t[rt]=x,sz[rt]=1,am[rt]++;return;} 23 while(k) fa=k,++sz[k],k=s[k][x>t[k]]; 24 k=s[fa][x>t[fa]]=++hd; 25 t[k]=x,sz[k]=1,f[k]=fa,am[k]++; 26 splay(k); 27 } 28 long long find2(long long k,long long x){ 29 if(x<=sz[s[k][0]]) return find2(s[k][0],x); 30 if(x==sz[s[k][0]]+1) return t[k]; 31 return find2(s[k][1],x-sz[s[k][0]]-1); 32 } 33 char r_w[30],r_l; 34 long long read(long long &x){ 35 while(r_w[0]=getchar(),r_w[0]<'0'||r_w[0]>'9');r_l=1,x=0; 36 while(r_w[r_l]=getchar(),r_w[r_l]>='0'&&r_w[r_l]<='9') r_l++; 37 for(long long i=0;i<r_l;i++) x=x*10+r_w[i]-'0'; 38 } 39 void write(long long x){ 40 if(!x) return; 41 write(x/10); 42 putchar(x%10+'0'); 43 } 44 int main(){ 45 freopen("rollcall.in","r",stdin); 46 freopen("rollcall.out","w",stdout); 47 read(n),read(m); 48 for(long long i=1;i<=n;i++) read(ss[i]); 49 ins(rt,ss[1],0); 50 for(long long i=1,j=1;i<=m;i++){ 51 read(a); 52 while(j<a) ins(rt,ss[++j],0); 53 54 b=find2(rt,i); 55 if(b) write(b); 56 else putchar('0'); 57 putchar('\n'); 58 } 59 return 0; 60 }